从 AWS lambda@edge 访问源 URL

accessing origin URL from AWS lambda@edge

我正在尝试在 AWS Cloudfront 上使用 lambda@edge 为多个网站实施 "proxy"。

我的设置大致是:

DNS: *.domain.com -> some_uuid.cloudfront.net(云端分布)

Cloudfront:some_uuid.cloudfront.net -> s3 存储桶来源

s3 bucket: websites/(包含多个网站的文件夹)

lambda@edge 函数:定义为origin-request

我的 lambda@edge 函数非常简单:

  1. 检查s3 bucket中是否存在网站资源

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

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

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

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

还有其他解决办法吗?

谢谢

所以你的用例的问题是暴露给你的 origin-request L@E 函数的主机 header 的值是 s3 存储桶的域名,而不是原始主机header CloudFront 已收到来自查看者的信息,对吗?

为了查看从查看器收到的原始主机 header CloudFront,您需要将其列入白名单。但是,CloudFront 当前不允许将 s3 来源的 headers 列入白名单。这是一个应该由 CloudFront 修复的 bug/limitation。不过有一个解决方法。如果 s3 存储桶可公开访问(即您未使用源访问身份),您可以使用 mybucket.s3-website-us-east-1.amazonaws.com 等网站端点将 S3 源配置为自定义源。然后,您将能够将主机 header 列入白名单,并根据浏览者的要求查看您网站的域名。然后,您可以根据您的用例修改原始请求。也不要忘记将主机 header 更改回 s3 端点,以便 S3 接受请求。

这里的主要问题是 Cloudfront 在对原始主机的请求中覆盖了主机 header。 我可以通过组合使用 viewer-request L@E 和 origin-request L@E.

来解决这个问题

在查看器请求 L@E 中将主机 header 复制到另一个 header,如 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)
}

在行为中将您的云端配置为白名单 x-forwarded-host 主机 header。 这样,Cloudfront 在缓存时也会考虑 x-forwarded-host,并将 header 传递给 origin-request lambda

所以现在在您的 origin-request lambda 中您可以访问 x-forwarded-host header

// 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);
}