【问题标题】:Device based redirection on CloudFront serving from S3 origin从 S3 源提供服务的 CloudFront 上基于设备的重定向
【发布时间】:2018-03-02 06:19:47
【问题描述】:

有没有办法使用 CloudFront 根据 User Agent 标头将用户重定向到 Web 应用程序的移动版本,例如 m.foobar.com

我确实使用CloudFront-Is-Mobile-Viewer 标头阅读了使用用户设备类型的标头缓存。但是,如果我使用自定义源来服务我的资产(ELB 或 EC2 实例),我只能将其列入白名单。在这种情况下,我可以编辑我的服务器配置来处理重定向。

但是,我现在使用 S3 为我的应用程序提供服务,并且更喜欢 CloudFront/S3 生态系统中的解决方案。

编辑: 对于 S3 发行版,我无权访问 CloudFront-Is-Mobile-Viewer 和其他 CF 标头。

任何帮助,指针将不胜感激!

背景素材:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html https://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/

【问题讨论】:

    标签: amazon-web-services amazon-s3 url-redirection amazon-cloudfront


    【解决方案1】:

    如何使用此代码为 nodejs 添加解码器,我使用此代码但它给了我一个字符串(如何解码它的 URi 字符串) 很抱歉,因为我的声誉低,所以我添加它来回答

    exports.handler = (event, context, callback) => {
    const name = 'cloudfront-is-mobile-viewer';
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    
    if (headers[name] && headers[name][0].value == "true") {
         callback(null, {
            status:'302',
            statusDescription: 'Found',
               headers: {
            location: [{
                key: 'Location',
                value: `http://m.example.com${request.uri}`,
            }]
        }
    })
    

    }

    回调(空,请求); };

    【讨论】:

      【解决方案2】:

      目前在 viewer response 我们无法访问 CloudFront-Is-X-Viewer 标头,即使将它们设置为白名单,而且 status 标头是只读的.我通过origin request触发解决了这个问题:

      exports.handler = (event, context, callback) => {
      const name = 'cloudfront-is-mobile-viewer';
      const request = event.Records[0].cf.request;
      const headers = request.headers;
      
      if (headers[name] && headers[name][0].value == "true") {
          callback(null, {
              status:'302',
              statusDescription: 'Found',
              headers: {
                  location: [{
                      key: 'Location',
                      value: `http://m.example.com${request.uri}`,
                  }]
              }
          })
      }
      
      callback(null, request);
      

      };

      【讨论】:

        【解决方案3】:

        这是我的解决方法。

        Lambda@Edge 函数

        'use strict';
        
        exports.handler = (event, context, callback) => {
            /*
             * If mobile, redirect to mobile domain
            */
            const isMobileHeader = 'CloudFront-Is-Mobile-Viewer'
        
            const request = event.Records[0].cf.request;
            const headers = request.headers;
        
            let response = event.Records[0].cf.response;
            if (headers[isMobileHeader.toLowerCase()] && headers[isMobileHeader.toLowerCase()] == "true") {
                response = {
                status: '302',
                statusDescription: 'Found',
                headers: {
                    location: [{
                        key: 'Location',
                        value: 'http://m.foobar.com',
                    }],
                },
            };
        
            callback(null, response);
        };
        

        CloudFront 分发

        Behaviours:
          Default:
            Cache Based on Selected Request Headers: Whitelist
            Whitelist Headers:
              - CloudFront-Is-Mobile-Viewer
            Lambda Function Associations:
              Event Type: Viewer Response
              Lambda Function ARN:  [ARN of function from Lambda@Edge Function]
        

        进一步阅读

        编辑 1

        原来 S3 起源,正如 Sanjay 指出的那样,是 limited to a select set of headers for caching

        我的建议是使用 S3 Static Website hosting 从 S3 Origin 更改为 Custom Origin,然后我们可以将其定位为自定义 Origin。

        S3 存储桶配置

        S3 Bucket:
          Properties:
            Static Website Hosting: Use this bucket to host a website
        

        记下您在此页面上提供的端点名称,下一步将需要它。

        CloudFront 更新

        Origins:
          Create Origin:
            Origin Domain Name: [Endpoint from above]
            Origin ID: Custom-S3StaticHosting
        Behaviours:
          Default:
            Origin: Custom-S3StaticHosting
        

        【讨论】:

        • 如果我要使用 ELB 源转发我的内容,该解决方案非常适合。但看似,白名单标头CloudFront-Is-Mobile-Viewer 不适用于S3 分发。对于 S3 发行版,只有 3 个标头是“可列入白名单的”:Access-Control-Request-MethodAccess-Control-Request-HeadersOrigin
        • 如果您使用像[bucket].s3-website-[region].amazonaws.com 这样的静态网站端点会怎样。该值也可以在您的 s3 存储桶的 Static Website Hosting 设置页面上找到。
        • 我的origin是S3 bucket的全限定域名,格式有点像xxxx.s3.amazonaws.com。 AWS 文档 (docs.aws.amazon.com/AmazonS3/latest/dev/…) 上的所有网站重定向文档都解决了基于键、错误等的静态重定向;但没有一个基于动态属性,如用户位置/设备。
        • 通过从 S3 来源 更改为 自定义来源 更新了我的答案以解决此问题
        • 我在 aws 文档中看到了 headers['cloudfront-is-mobile-viewer'] && headers['cloudfront-is-mobile-viewer'][0].value === 'true'(docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…)。也许 aws 更新了他们的标题?
        【解决方案4】:

        这是我的解决方法。

        您无需为移动应用执行重定向。 (尽可能避免重定向)您可以使用相同的 url 来提供桌面或移动内容。

        在您的云端白名单中,只需将 CloudFront-Is-Mobile-Viewer 标头列入白名单。这将根据您的设备缓存内容。

        实现查看器请求 Lambda Edge 并将其添加到 CloudFront。 Lambda Edge 是在请求​​到达服务器之前对 pop 或 CloudFront 进行编程。

        在 LambdaEdge 中,验证 User-Agent 标头并分类您是要提供移动内容还是桌面内容。如果是移动设备,那么您可以将源网址更改为从移动内容提供服务,否则您可以将其更改为桌面内容或默认内容。

        您在用户请求 LambdaEdge 中获取您的 http 标头。

        Lambda 边缘文档:

        http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html

        参考页面上提供了示例节点实现。

        如果您真的想执行重定向,您可以通过查看器响应来执行此操作,并根据收到的设备标头做出决定。

        本博客介绍了查看者响应的示例实现,

        https://aws.amazon.com/blogs/aws/lambdaedge-intelligent-processing-of-http-requests-at-the-edge/

        上面的实现只是吐回它收到的所有标头,而不是发送 200 OK,代码需要修改为带有重定向位置的 3xx 状态。

        希望对你有帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-11
          • 2014-05-09
          • 2021-12-06
          • 2021-04-12
          • 2021-01-26
          • 2015-05-16
          • 2016-06-06
          • 2015-09-08
          相关资源
          最近更新 更多