Amazon web services 基于来自S3源的CloudFront服务的基于设备的重定向

Amazon web services 基于来自S3源的CloudFront服务的基于设备的重定向,amazon-web-services,amazon-s3,url-redirection,amazon-cloudfront,Amazon Web Services,Amazon S3,Url Redirection,Amazon Cloudfront,是否有一种方法可以使用CloudFront根据用户代理标题将用户重定向到web应用的移动版本,比如m.foobar.com 我确实使用CloudFront Is Mobile Viewerheader阅读了使用用户设备类型的header缓存。但是,只有在使用自定义源来服务我的资产(ELB或EC2实例)时,我才能将其列入白名单。在这种情况下,我可以编辑服务器配置来处理重定向 但是,我现在使用S3为我的应用程序提供服务,我更喜欢CloudFront/S3生态系统中的解决方案 编辑: 对于S3发行版,

是否有一种方法可以使用CloudFront根据
用户代理
标题将用户重定向到web应用的移动版本,比如
m.foobar.com

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

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

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

任何帮助,指点者将不胜感激

背景材料:
以下是我将如何解决它

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

在cloudfront白名单中,只有白名单
cloudfront是Mobile Viewer
标题。这将根据您的设备缓存内容

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

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

您可以在用户请求lambdedge中获取http头

Lambda边缘文档:

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

如果确实要执行重定向,可以使用查看器响应执行重定向,并根据接收到的设备头做出决定

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

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


希望能有帮助。

以下是我解决问题的方法

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);
};
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]
S3 Bucket:
  Properties:
    Static Website Hosting: Use this bucket to host a website
云端分布

'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);
};
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]
S3 Bucket:
  Properties:
    Static Website Hosting: Use this bucket to host a website
进一步阅读

编辑1

正如Sanjay指出的,S3的起源是

我的建议是从S3源代码更改为自定义源代码,使用,然后我们可以将其作为自定义源代码

S3存储桶配置

'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);
};
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]
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

目前在查看器响应中我们无法访问CloudFront-Is-X-viewer标题,即使将其设置为白名单,而且状态标题是只读的。我已通过在原始请求触发解决了此问题:

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);

})

如何使用此代码为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}`,
        }]
    }
})
}

回调(null,请求);
};

如果我要使用ELB来源转发我的内容,那么这个解决方案是一个完美的选择。但是,白名单标题
CloudFront Is Mobile Viewer
似乎不适用于S3发行版。对于S3发行版,只有3个头是“可白名单”的:
访问控制请求方法
访问控制请求头
源文件
。如果使用静态网站端点,如
[bucket].S3网站-[region].amazonaws.com
,会怎么样。这个值也可以在s3 bucket的静态网站托管设置页面上找到。我的来源是s3 bucket的完全限定域名,其格式类似于xxxx.s3.amazonaws.com。AWS文档()上的所有网站重定向文档都基于密钥、错误等解决了静态重定向问题。;但是没有一个是基于动态属性的,比如用户位置/设备。通过将S3源代码更改为自定义源代码,更新了我的答案以说明这一点。我看到了
headers['cloudfront-is-mobile-viewer']&&headers['cloudfront-is-mobile-viewer'][0]。value==='true'
from aws docs()。也许aws更新了他们的标题?