简体   繁体   English

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

[英]Multiple Cloudfront Origins with Behavior Path Redirection

I have two S3 buckets that are serving as my Cloudfront origin servers:我有两个 S3 存储桶用作我的 Cloudfront 源服务器:

example-bucket-1
example-bucket-2

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.我正在尝试将我的 Cloudfront 分发配置为基于 URL 模式进行路由或重写。 For example, with these files例如,使用这些文件

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

I would like to make these URLs point to the respective files我想让这些 URL 指向相应的文件

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

I tried setting up cache behaviors that match the path1 and path2 patterns, but it doesn't work.我尝试设置匹配 path1 和 path2 模式的缓存行为,但它不起作用。 Do the patterns have to actually exist in the S3 bucket?这些模式是否必须实际存在于 S3 存储桶中?

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.更新:原始答案(如下所示)在 2015 年编写时是准确的,并且基于 CloudFront 本身的内置行为是正确的。 Originally, the entire request path needed to exist at the origin.最初,整个请求路径需要存在于原点。

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.如果 URI 是/download/images/cat.png但源只需要/images/cat.png那么 CloudFront 缓存行为/download/*将不会执行您可能假设的操作——缓存行为的路径模式仅用于匹配-- 匹配的前缀不会被删除。

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.在向源发送请求时,CloudFront 本身不提供从浏览器请求的路径中删除元素的方法。 The request is always forwarded as it was received, or with extra characters at the beginning, if the origin path is specified.如果指定了原始路径,则请求总是在收到时转发,或者在开头带有额外的字符。

However, the introduction of Lambda@Edge in 2017 changes the dynamic.然而,2017 年Lambda@Edge的引入改变了动态。

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

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.在 Origin Request 触发器中使用时,响应缓存在浏览器请求的路径下,因此不需要重写后续响应——它们可以从缓存中提供——并且触发器不需要触发对于每个请求。

Lambda@Edge functions can be quite simple to implement. Lambda@Edge 函数的实现非常简单。 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
};

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 ..replace(/^\\/[^\\/]+\\//,'/') ,我们将 URI 与匹配前导/后跟 1 个或多个不能是/字符的正则表达式匹配,然后再添加一个/ ,并用单个/替换整个匹配项——因此无论abc的确切值如何,路径都会从/abc/def/ghi/...重写为/def/ghi/... 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.这可能会变得更复杂以适应特定的要求,而不会显着增加执行时间……但请记住,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.要简单地在来自浏览器的请求中添加前缀,仍然可以使用 Origin Path 设置,如下所述,但删除或修改路径组件需要 Lambda@Edge,如上所述。


Original answer .原答案

Yes, the patterns have to exist at the origin.是的,模式必须存在于原点。

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). CloudFront 本身可以预先添加到给定源的路径,但它目前没有删除路径元素的能力(没有 Lambda@Edge,如上所述)。

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."如果您的文件在源的/secret/files/中,您可以通过设置“源路径”在将请求发送到源之前转换路径模式/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/* .如果文件位于/files中,则没有内置方法可以从路径模式/download/files/*提供这些文件。

You can add (prefix) but not take away.您可以添加(前缀)但不能删除。

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.一个相对简单的解决方法是在与 S3 存储桶位于同一区域的 EC2 实例上使用反向代理服务器,将 CloudFront 指向代理,将代理指向 S3。 The proxy would rewrite the HTTP request on its way to S3 and stream the resulting response back to CloudFront.代理将在到达 S3 的途中重写 HTTP 请求,并将结果响应流式传输回 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). (我开发的反向代理软件实际上可以并行或串行检查多个存储桶,并将它收到的第一个非错误响应返回给 CloudFront 和请求者)。

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.或者,如果使用 S3 网站终端节点作为自定义源,您可以使用 S3 重定向路由规则将重定向返回到 CloudFront,将删除未处理前缀的浏览器发送回。 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.这意味着对每个对象都有一个额外的请求,在一定程度上增加了延迟和成本,但 S3 重定向规则可以设置为仅在请求实际上与存储桶中的文件不匹配时触发。 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/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM