CloudFront忽略了Lambda @ Edge

时间:2019-03-31 03:38:47

标签: amazon-web-services amazon-s3 aws-lambda amazon-cloudfront

我正在尝试配置 CloudFront ,以便它根据的值从 S3 外部来源获取内容。 >标题

为此,我实现了 Lambda @ Edge ,该事件在 Origin Request 事件中触发。它将来源更改为自定义来源,但是,以某种方式,CloudFront仍仍在访问S3 内容。

这是Lambda函数:

'use strict';

const PRERENDER_HOST = 'xxxxx.ngrok.io'
const IS_SSL = false

exports.handler = (event, context, callback) => {
    console.log('event', JSON.stringify(event))
    const request = event.Records[0].cf.request;
    const headers = request.headers;
    const should_prerender = headers['x-should-prerender'] 
            ? JSON.parse(headers['x-should-prerender'][0].value)
            : false

    console.log('should prerender', should_prerender, 'existed', !!headers['x-should-prerender'])
    console.log('uri is', request.uri)
    if (should_prerender) {
        set_header('host', PRERENDER_HOST, headers)
        request.origin = {
            custom: {
                domainName: PRERENDER_HOST,
                port: IS_SSL ? 443 : 80,
                protocol: IS_SSL ? 'https' : 'http',
                readTimeout: 20,
                keepaliveTimeout: 5,
                customHeaders: {},
                path: request.uri,
                sslProtocols: ['TLSv1', 'TLSv1.1'],
            }
        }
    }

    console.log('request', JSON.stringify(request))

    callback(null, request)

    function set_header(name, value, store) {
        store[name.toLowerCase()] = [
            {
                key: name,
                value
            }
        ]
    }
};

接下来,我将粘贴传递到request的{​​{1}}的内容。这已从相关的CloudWatch日志中提取。日志显示了如何建立自定义来源。

callback

有什么想法在这里发生吗?

更新1 :尝试使用{ "uri" : "/index.html", "origin" : { "custom" : { "sslProtocols" : [ "TLSv1", "TLSv1.1" ], "keepaliveTimeout" : 5, "port" : 80, "domainName" : "xxxxx.ngrok.io", "path" : "/index.html", "customHeaders" : {}, "readTimeout" : 20, "protocol" : "http" } }, "headers" : { "x-should-prerender" : [ { "key" : "x-should-prerender", "value" : "true" } ], "host" : [ { "key" : "host", "value" : "xxxxx.ngrok.io" } ], "upgrade-insecure-requests" : [ { "value" : "1", "key" : "Upgrade-Insecure-Requests" } ], "dnt" : [ { "key" : "DNT", "value" : "1" } ], "x-forwarded-for" : [ { "key" : "X-Forwarded-For", "value" : "xxx.xxx.xx.xx" } ], "via" : [ { "value" : "1.1 25xxxxxbcxxxx07847a7xxxxxx.cloudfront.net (CloudFront)", "key" : "Via" } ], "user-agent" : [ { "key" : "User-Agent", "value" : "Amazon CloudFront" } ], "accept-encoding" : [ { "key" : "Accept-Encoding", "value" : "gzip" } ] }, "clientIp" : "xxx.xx.xx.xxx", "querystring" : "", "method" : "GET" } 后,一切正常。不过,不知道为什么它不能与https一起使用。 更新2 :更正一个错误。我写了View Request而不是Origin Request。感谢Michael的注意。

1 个答案:

答案 0 :(得分:1)

查看器请求触发器在CloudFront的“前端”(查看器端)运行,这在缓存检查之前。

在这一点上原点是“已知的”,因为已经进行了“缓存行为”匹配,但是您无法在查看器端影响原点选择,因为CloudFront尚未从技术上决定是否联系原点。

只能在CloudFront的Origin Request触发器中在CloudFront的原始端(缓存检查后,在背面)上进行对原始服务器的更改。查看者请求触发器更改原点是没有意义的,因为原点不是缓存键的一部分,因此,如果查看者请求触发器更改了原点,则将检查缓存而不会为缓存做任何调整。更改了原点,因此无法保证缓存的响应甚至来自正确的位置。

您将需要使用“原始请求”触发器,并且需要将x-should-prerender列入白名单以转发到原始位置(在“缓存行为”设置中),以便触发器可以看到它。如果您不希望原产地实际看到它,则需要使用触发代码将其删除,但是必须将其列入白名单,以使原产地请求触发器能够看到它。

  

如果您希望函数以一种影响原始响应的方式更改请求,请使用原始请求事件。

     

http://registry.example.com/test