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

查看:86
本文介绍了具有行为路径重定向的多个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 改变了动态。

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.

此选项不会修改哪个缓存行为将实际为请求提供服务,因为它始终基于浏览器所请求的路径-但是您可以随后动态修改路径,以使实际的请求对象位于浏览器请求的路径以外的路径。在原始请求触发器中使用时,响应将缓存在浏览器所请求的路径下,因此不需要重写后续响应-可以从缓存中为它们提供服务-无需触发触发器

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函数可以很容易实现。这是一个示例函数,它将删除第一个path元素,不管它是什么。

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 <的确切值如何/ code>。可以使其变得更复杂以适应特定的需求,而不会显着增加执行时间...但是请记住,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.

只需在请求中添加前缀即可在浏览器中,仍然可以使用原始路径设置,如下所述,但是要删除或修改路径组件,需要如上所述的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 / latest / dev / HowDoIWebsiteConfiguration.html

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

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