具有行为路径重定向的多个 Cloudfront 源

Posted

技术标签:

【中文标题】具有行为路径重定向的多个 Cloudfront 源【英文标题】:Multiple Cloudfront Origins with Behavior Path Redirection 【发布时间】:2015-10-12 14:46:17 【问题描述】:

我有两个 S3 存储桶用作我的 Cloudfront 源服务器:

example-bucket-1
example-bucket-2

两个存储桶的内容都位于这些存储桶的根目录中。我正在尝试将我的 Cloudfront 分发配置为基于 URL 模式进行路由或重写。例如,使用这些文件

example-bucket-1/something.jpg
example-bucket-2/something-else.jpg

我想让这些 URL 指向各自的文件

http://example.cloudfront.net/path1/something.jpg
http://example.cloudfront.net/path2/something-else.jpg

我尝试设置与 path1 和 path2 模式匹配的缓存行为,但它不起作用。模式是否必须实际存在于 S3 存储桶中?

【问题讨论】:

【参考方案1】:

更新:下面显示的原始答案在 2015 年编写时是准确的,并且基于 CloudFront 本身的内置行为是正确的。最初,整个请求路径需要存在于源头。

如果 URI 是 /download/images/cat.png,但源仅需要 /images/cat.png,则 CloudFront 缓存行为 /download/* 不会像您假设的那样 - 缓存行为的路径模式仅用于匹配 - 匹配的前缀是没有被删除。

CloudFront 本身不提供在向源发送请求时从浏览器请求的路径中删除元素的方法。如果指定了源路径,则始终会在收到请求时转发请求,或者在开头带有额外字符。

但是,2017 年 Lambda@Edge 的引入改变了动态。

Lambda@Edge 允许您在 CloudFront 流中声明触发器挂钩并编写小的 javascript 函数来检查和修改传入请求,无论是在检查 CloudFront 缓存之前(查看器请求)还是在检查缓存之后(来源要求)。这允许您重写请求 URI 中的路径。例如,您可以将来自/download/images/cat.png 的浏览器的请求路径转换为删除/download,从而将/images/cat.png 的请求发送到S3(或自定义源)。

此选项不会修改实际为请求提供服务的缓存行为,因为这始终基于浏览器请求的路径 - 但您可以在运行中修改路径,以便实际请求的对象位于与浏览器请求的路径不同的路径。在 Origin Request 触发器中使用时,响应缓存在浏览器请求的路径下,因此不需要重写后续响应——它们可以从缓存中提供——并且触发器不需要触发每个请求。

Lambda@Edge 函数的实现非常简单。这是一个示例函数,它将删除第一个路径元素,无论它是什么。

'use strict';

// lambda@edge Origin Request trigger to remove the first path element
// compatible with either Node.js 6.10 or 8.10 Lambda runtime environment

exports.handler = (event, context, callback) => 
    const request = event.Records[0].cf.request;           // extract the request object
    request.uri = request.uri.replace(/^\/[^\/]+\//,'/');  // modify the URI
    return callback(null, request);                        // return control to CloudFront
;

就是这样。在.replace(/^\/[^\/]+\//,'/') 中,我们将URI 与匹配前导/ 的正则表达式匹配,后跟1 个或多个不能为/ 的字符,然后再添加一个/,并将整个匹配替换为单个/ - 因此无论abc 的确切值如何,路径都会从/abc/def/ghi/... 重写为/def/ghi/...。这可以变得更复杂以满足特定要求,而不会显着增加执行时间......但请记住,Lambda@Edge 函数与一个或多个缓存行为相关联,因此您不需要单个函数来处理 all 请求通过分发 - 只是与相关缓存行为的路径模式匹配的请求。

要简单地为来自浏览器的请求添加前缀,仍然可以使用 Origin Path 设置,如下所述,但删除或修改路径组件需要 Lambda@Edge,如上所述。


原答案

是的,模式必须存在于原点。

CloudFront 本身可以预先添加到给定源的路径,但它目前不具备删除路径元素的能力(如上所述,没有 Lambda@Edge)。

如果您的文件位于源的/secret/files/,您可以通过设置“源路径”在将请求发送到源之前转换路径模式/files/*

反之则不然。如果文件位于原点的/files 中,则没有内置方法可以从路径模式/download/files/* 提供这些文件。

您可以添加(前缀)但不能删除。

一个相对简单的解决方法是在与 S3 存储桶位于同一区域的 EC2 实例上使用反向代理服务器,将 CloudFront 指向代理,将代理指向 S3。代理将在前往 S3 的途中重写 HTTP 请求,并将生成的响应流式传输回 CloudFront。我使用这样的设置,它的性能从未让我失望。 (我开发的反向代理软件实际上可以并行或串行检查多个存储桶,并将它收到的第一个非错误响应返回给 CloudFront 和请求者)。

或者,如果使用 S3 网站终端节点作为自定义源,您可以使用 S3 重定向路由规则将重定向返回到 CloudFront,将浏览器发送回来并删除未处理的前缀。这意味着对每个对象都有一个额外的请求,从而在一定程度上增加了延迟和成本,但是可以将 S3 重定向规则设置为仅在请求实际上与存储桶中的文件不匹配时触发。这对于从一种层次结构过渡到另一种层次结构很有用。

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html

http://docs.aws.amazon.com/AmazonS3/latest/dev/HowDoIWebsiteConfiguration.html

【讨论】:

新版本(使用 Lambda)也适用于我。值得注意的是,我还可以通过在存储桶中添加一个文件夹来使其工作,但这让事情变得一团糟:) 2021 年更新:advancedweb.hu/… 解释了 Cloudfront functions 在这个重写问题上如何优于 lambda@edge。

以上是关于具有行为路径重定向的多个 Cloudfront 源的主要内容,如果未能解决你的问题,请参考以下文章

Cloudfront:设置与 Origin 的 s3 路径差异

CloudFront 使用路径前缀重定向所有请求

AWS CloudFront 重定向到路径

如何在使用 CloudFront 函数重定向请求时包含 HTTP 请求正文?

AWS CloudFront 重定向到 S3 存储桶

在 Route53 和 CloudFront 中将 www 重定向到非 www