具有行为路径重定向的多个 Cloudfront 源 [英] Multiple Cloudfront Origins with Behavior Path Redirection

查看:32
本文介绍了具有行为路径重定向的多个 Cloudfront 源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two S3 buckets that are serving as my Cloudfront origin servers:

example-bucket-1
example-bucket-2

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

The contents of both buckets live in the root of those buckets. I am trying to configure my Cloudfront distribution to route or rewrite based on a URL pattern. For example, with these files

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

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

I would like to make these URLs point to the respective files

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

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

I tried setting up cache behaviors that match the path1 and path2 patterns, but it doesn't work. Do the patterns have to actually exist in the S3 bucket?

推荐答案

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

Update: the original answer, shown below, is was accurate when written in 2015, and is correct based on the built-in behavior of CloudFront itself. Originally, the entire request path needed to exist at the origin.

如果 URI 是 /download/images/cat.png 但源只需要 /images/cat.png 然后 CloudFront 缓存行为 /download/* 不会做你可能假设的事情——缓存行为的路径模式仅用于匹配——匹配的前缀不会被删除.

If the URI is /download/images/cat.png but the origin expects only /images/cat.png then the CloudFront Cache Behavior /download/* will not do what you might assume -- the cache behavior's path pattern is only for matching -- the matched prefix isn't removed.

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

By itself, CloudFront doesn't provide a way to remove elements from the path requested by the browser when sending the request to the origin. The request is always forwarded as it was received, or with extra characters at the beginning, if the origin path is specified.

但是,Lambda@Edge 的引入 在 2017 年变化的动态.

However, the introduction of Lambda@Edge in 2017 changes the dynamic.

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

Lambda@Edge allows you to declare trigger hooks in the CloudFront flow and write small Javascript functions that inspect and can modify the incoming request, either before the CloudFront cache is checked (viewer request), or after the cache is checked (origin request). This allows you to rewrite the path in the request URI. You could, for example, transform a request path from the browser of /download/images/cat.png to remove /download, resulting in a request being sent to S3 (or a custom orgin) for /images/cat.png.

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

This option does not modify which Cache Behavior will actually service the request, because this is always based on the path as requested by the browser -- but you can then modify the path in-flight so that the actual requested object is at a path other than the one requested by the browser. When used in an Origin Request trigger, the response is cached under the path requested by the browser, so subsequent responses don't need to be rewritten -- they can be served from the cache -- and the trigger won't need to fire for every request.

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

Lambda@Edge functions can be quite simple to implement. Here's an example function that would remove the first path element, whatever it may be.

'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/def/ghi/... 重写为 /def/ghi/... 而不管 的确切值abc.这可能会变得更复杂以适应特定的要求,而不会显着增加执行时间……但请记住,Lambda@Edge 函数与一个或多个缓存行为相关联,因此您不需要单个函数来处理 所有通过分发的请求——只是与相关缓存行为的路径模式匹配的请求.

That's it. In .replace(/^/[^/]+//,'/'), we're matching the URI against a regular expression that matches the leading / followed by 1 or more characters that must not be /, and then one more /, and replacing the entire match with a single / -- so the path is rewritten from /abc/def/ghi/... to /def/ghi/... regardless of the exact value of abc. This could be made more complex to suit specific requirements without any notable increase in execution time... but remember that a Lambda@Edge function is tied to one or more Cache Behaviors, so you don't need a single function to handle all requests going through the distribution -- just the request matched by the associated cache behavior's path pattern.

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

To simply prepend a prefix onto the request from the browser, the Origin Path setting can still be used, as noted below, but to remove or modify path components requires Lambda@Edge, as above.

原始答案.

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

Yes, the patterns have to exist at the origin.

CloudFront 本身可以前置到给定源的路径,但它目前没有删除路径元素的能力(没有 Lambda@Edge,如上所述).

CloudFront, natively, can prepend to the path for a given origin, but it does not currently have the capability of removing elements of the path (without Lambda@Edge, as noted above).

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

If your files were in /secret/files/ at the origin, you could have the path pattern /files/* transformed before sending the request to the origin by setting the "origin path."

事实并非如此.如果文件在源的 /files 中,则没有内置方法从路径模式 /download/files/* 提供这些文件.

The opposite isn't true. If the files were in /files at the origin, there is not a built-in way to serve those files from path pattern /download/files/*.

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

You can add (prefix) but not take away.

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

A relatively simple workaround would be a reverse proxy server on an EC2 instance in the same region as the S3 bucket, pointing CloudFront to the proxy and the proxy to S3. The proxy would rewrite the HTTP request on its way to S3 and stream the resulting response back to CloudFront. I use a setup like this and it has never disappointed me with its performance. (The reverse proxy software I developed can actually check multiple buckets in parallel or series and return the first non-error response it receives, to CloudFront and the requester).

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

Or, if using the S3 Website Endpoints as the custom origins, you could use S3 redirect routing rules to return a redirect to CloudFront, sending the browser back with the unhandled prefix removed. This would mean an extra request for each object, increasing latency and cost somewhat, but S3 redirect rules can be set to fire only when the request doesn't actually match a file in the bucket. This is useful for transitioning from one hierarchical structure to another.

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

http://docs.aws.amazon.com/AmazonS3/最新/开发/HowDoIWebsiteConfiguration.html

这篇关于具有行为路径重定向的多个 Cloudfront 源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆