我正在尝试使用AWS Cloudfront上的lambda @ edge为多个网站实施“代理”。
我的设置大致是:
DNS:* .domain.com - > some_uuid.cloudfront.net(Cloudfront分发)
Cloudfront:some_uuid.cloudfront.net - > s3桶起源
s3 bucket:网站/(包含多个网站的文件夹)
lambda @ edge函数:定义为origin-request
我的lambda @ edge函数非常简单:
检查s3存储桶中是否存在网站资源。
如果是,请将请求uri更改为资源s3网址。
如果没有,请向后端服务器发送请求以呈现资源,存储在s3上并将其返回。
我无法获取网站的原始域名。例如,如果我尝试访问“my_website.domain.com” - 在我的lambda函数中,我没有来自请求的域信息。
我想我可以实现另一个lambda @ edge函数作为查看器请求将域作为标题传递,但如果可以,我宁愿避免这种情况。
还有其他解决方案吗?
由于
答案 0 :(得分:3)
这里的主要问题是Cloudfront会将请求中的主机标头覆盖到原始主机。 我可以通过结合使用查看者请求L @ E和原始请求L @ E来解决此问题。
在查看器请求中,L @ E将主机标头复制到另一个标头,例如x-forwarded-host。
// viewer-request.js
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request
request.headers['x-forwarded-host'] = [
{ key: 'X-Forwarded-Host', value: request.headers.host[0].value }
]
return callback(null, request)
}
将您的Cloudfront配置为在行为中将x-forwarded-host
主机标头列入白名单。
这样,Cloudfront在缓存时还考虑了x-forwarded-host
,并且还将标头传递到origin-request lambda
。
因此,现在在您的原始请求lambda中,您可以访问x-forwarded-host
标头
// origin-request.js
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const requestHost = headers['x-forwarded-host'][0].value;
console.log(requestHost);
callback(null, request);
}
答案 1 :(得分:2)
因此,您的用例的问题是,暴露给您的origin-request L @ E函数的主机头的值是s3存储桶的域名,而不是CloudFront从查看器收到的原始主机头,正确的吗?
要查看从查看器收到的原始主机标头CloudFront,您需要将其列入白名单。但是,CloudFront目前不允许将s3来源的标题列入白名单。这是一个应该由CloudFront修复的错误/限制。但有一个解决方法。如果s3存储桶可公开访问(即您未使用原始访问标识),则可以使用网站端点(如mybucket.s3-website-us-east-1.amazonaws.com)将S3源配置为自定义源。然后,您将能够将主机标题列入白名单,并根据查看者的请求查看您网站的域名。然后,您可以根据您的使用情况修改原始请求。不要忘记将主机头更改回s3端点,以便S3接受请求。