CloudFront Lambda@Edge HTTPS 重定向

CloudFront Lambda@Edge HTTPS redirect

我有一个 CloudFront 分配,其中一个 Lambda 函数附加到查看器请求挂钩。我正在使用它来重定向到规范域(例如 www.foo.tld -> foo.tld)。我还将分发本身设置为重定向 HTTP -> HTTPS。

问题在于,这需要客户端可能必须执行 2 次请求才能到达正确的 URL。例如:

http://www.foo.tld/ -> https://www.foo.tld/ (performed by CloudFront)
https://www.foo.tld/ -> https://foo.tld/ (performed by Lambda function attached to viewer request hook)

我想在 1 个请求中完成此操作:

http://www.foo.tld/ -> https://foo.tld/

看起来我需要将此功能添加到请求事件中,但 documentation 似乎表明该协议未在请求事件中暴露给 Lambda 函数。

我的问题是:

旁注:重定向改变 both 主机名 and 该方案可能有问题,未来比现在更多,因为浏览器对没有 TLS 的 HTTP 行为的接受度降低。目前,我不知所措,无法引用来源来支持这一点,但我的印象是将 直接 http://www.example.com 重定向到 https://example.com 应该避免。不过,如果那是你想要的...


CloudFront 和 Lambda@Edge 支持这一点,但仅在源请求触发器中。

如果您在缓存行为设置中将 CloudFront-Forwarded-Proto header 列入白名单,您就可以像这样访问该值:

const request = event.Records[0].cf.request; // you may already have this
const scheme = request.headers['cloudfront-forwarded-proto'][0].value;

scheme 的值将是 httphttps

我有点迂腐,所以我喜欢故障保险。此替代版本将始终将 scheme 设置为 https 并避免因任何原因 header 不存在而引发的异常。这可能符合您的口味,也可能不符合您的口味:

const request = event.Records[0].cf.request; // you may already have this
const scheme = (request.headers['cloudfront-forwarded-proto'] || [{ value: 'https' }])[0].value;

这只能在源请求触发器中完成的原因是 CloudFront 实际上不会在内部添加这个 header 直到查看器请求触发器已经触发,如果有的话。

但还要注意,您几乎可以肯定想要在 Origin Request 触发器中执行此操作——因为来自这些触发器的响应可以被缓存……这应该意味着更快的响应和降低成本。将 header 列入白名单还会将其添加到缓存键中,这意味着 CloudFront 将自动缓存任何给定页面的单独 HTTP 和 HTTPS 响应,并且仅针对相同的请求重播它们。

另见 https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-cloudfront-star-headers