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

Ste*_*che 14 amazon-s3 amazon-web-services amazon-cloudfront

我有两个S3存储桶作为我的Cloudfront原始服务器:

example-bucket-1
example-bucket-2
Run Code Online (Sandbox Code Playgroud)

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

example-bucket-1/something.jpg
example-bucket-2/something-else.jpg
Run Code Online (Sandbox Code Playgroud)

我想让这些URL指向相应的文件

http://example.cloudfront.net/path1/something.jpg
http://example.cloudfront.net/path2/something-else.jpg
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*bot 31

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

如果URI /download/images/cat.png只是原点,/images/cat.png那么CloudFront Cache Behavior /download/*将不会执行您可能假设的操作 - 缓存行为的路径模式仅用于匹配 - 不会删除匹配的前缀.

就其本身而言,CloudFront不提供在将请求发送到源时从浏览器请求的路径中删除元素的方法.如果指定了原始路径,则始终在收到请求时转发请求,或者在开头添加额外字符.

然而,2017年Lambda @ Edge的推出改变了动态.

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

此选项不会修改哪个缓存行为将实际为请求提供服务,因为这始终基于浏览器请求的路径 - 但您可以修改路径中的路径,以便实际请求的对象位于其他路径而不是浏览器要求的那个.当在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
};
Run Code Online (Sandbox Code Playgroud)

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

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


原始答案.

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

本机CloudFront可以作为给定原点的路径前置,但它目前不具备删除路径元素的功能(没有Lambda @ Edge,如上所述).

如果您的文件/secret/files/位于原点,则可以/files/*在通过设置"原始路径"将请求发送到原点之前转换路径模式.

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

你可以添加(前缀)但不要带走.

一个相对简单的解决方法是与S3存储桶位于同一区域的EC2实例上的反向代理服务器,将CloudFront指向代理,将代理指向S3.代理将在前往S3的路上重写H​​TTP请求,并将生成的响应流回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)也适用于我。值得注意的是,我也可以通过在存储桶中添加一个文件夹来使其工作,但这使事情变得混乱:) (3认同)
  • 2021 年更新:https://advancedweb.hu/how-to-use-cloudfront-functions-to-change-the-origin-request-path/ 解释了在这个重写问题上,“Cloudfront 函数”如何优于 lambda@edge。 (2认同)