从AWS lambda @ edge访问原始URL

时间:2017-12-14 15:34:51

标签: javascript node.js aws-lambda amazon-cloudfront aws-lambda-edge

我正在尝试使用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函数非常简单:

  1. 检查s3存储桶中是否存在网站资源。

  2. 如果是,请将请求uri更改为资源s3网址。

  3. 如果没有,请向后端服务器发送请求以呈现资源,存储在s3上并将其返回。

  4. 我无法获取网站的原始域名。例如,如果我尝试访问“my_website.domain.com” - 在我的lambda函数中,我没有来自请求的域信息。

    我想我可以实现另一个lambda @ edge函数作为查看器请求将域作为标题传递,但如果可以,我宁愿避免这种情况。

    还有其他解决方案吗?

    由于

2 个答案:

答案 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接受请求。