【问题标题】:Lambda@Edge function not being called on Cloudfront error pageCloudfront 错误页面上未调用 Lambda@Edge 函数
【发布时间】:2021-02-15 08:27:13
【问题描述】:

我通过 Cloudfront 在 S3 存储桶上提供 Angular 应用程序的静态文件。我的 Cloudfront 发行版设置了错误页面,因此它仍然呈现 Angular 的 index.html。这意味着,如果我请求 <cloudfront-distribution>.cloudfront.net/home-page,而不是说它在 S3 存储桶上没有找到名为 home-page 的文件,它仍然会渲染 Angular 应用程序,而 Angular 应用程序将处理该 /home-page 路由。

我需要在应用服务器上包含一些安全标头,因此我设置了一个 Lambda@Edge 函数以在查看器响应事件中注入这些标头(如此处所述 https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/)。

Lambda@Edge 正在处理实际上对应于 S3 存储桶中的文件的路由(如果我在 S3 存储桶的根文件夹中有一个名为 image.png 的文件,并且我请求 <cloudfront-distribution>.cloudfront.net/image.png,我会看到我通过 Lambda@Edge 函数注入的响应标头。问题是访问与 S3 存储桶中的文件不对应的路由时。如果我访问 <cloudfront-distribution>.cloudfront.net/home-page,S3 将返回 404,Cloudfront 将处理 404并根据错误页面配置采取相应的行动,即响应 200 状态代码并呈现 index.html 文件。发生这种情况时,我看不到我通过 Lambda@Edge 函数注入的任何标头,而所有我的 Angular 应用程序的其他脚本文件有标题。

如何使所有响应都通过 Lambda@Edge 函数?

【问题讨论】:

  • 您能否确认您的 Lambda@Edge 已配置为在 Origin Response 事件上运行?
  • 其实没有。 Lambda@Edge 在查看器响应事件上运行。我尝试将其设置为 Origin Response,但结果根本没有标头(甚至在与 S3 存储桶上的文件匹配的路由上也没有)

标签: angular amazon-web-services amazon-s3 amazon-cloudfront aws-lambda-edge


【解决方案1】:

我刚刚经历了同样的情况。我发现 AWS 文档中的这个页面最有帮助:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html

虽然the current 的答案对于这个问题绝对正确,但我还有另一个可能有助于讨论的限制:

  • CloudFront 函数 仅针对查看器请求/响应事件触发;与 Lambda@Edge 函数 不同,后者可以由 Origin 或 Viewer 事件触发。就我而言,我想继续使用 CloudFront 功能,因为它们更轻/更快/更便宜。

正如您所观察到的(并在 the docs 中调用),当源出现错误时,不会触发查看器响应事件 - 包括自定义错误页面返回为 200 时。

选项 #1 - 切换到源请求事件

如果您已经在使用 Lambda@Edge 并且不想更改任何内容,这可能是最简单的更改。

  • 请记住,这发生在 CloudFront 中的任何缓存之前,因此不会再次调用缓存命中。因此可能不适用于所有用例。
  • 但是,这也可能是一件好事,因为它的 lambda 执行次数更少,并且标头应该包含在缓存中。

选项 #2 - 停止使用自定义错误响应

对我来说,我走了这条路。我需要为 Viewer Request 事件创建第二个函数,该函数重写任何不是专门针对 s3 资源的请求,以便 React Router 路径返回我的 index.html。 (类似这样的:https://stackoverflow.com/a/60012469/4413888)。最后,在 CloudFront 中删除了我现有的自定义错误响应。

  • 是的,这是在每个资源请求上执行的另一个函数,但是在 lambda@edge 调用的about 1/6 the cost(在免费层之后),我认为我仍然领先。
  • 获得从 s3 发现实际 403/404 的好处 - 比如当用户尝试加载旧的 webpack 块和死链接时

【讨论】:

  • 非常感谢您的分享!很有帮助!
【解决方案2】:

根据@philarmour 的回答,我将展示一个解决方案的具体示例。

删除您的 CloudFront 分配 中返回 /index.html 的自定义 404 页面。然后添加一个新的 CloudFront 函数(根据您的需要自定义下面的代码)

var rootPaths = {
    css: 1,
    favicon: 1,
    fonts: 1,
    img: 1,
    js: 1,
    'robots.txt': 1,
};
function handler(event) {
    var firstPart = event.request.uri.split('/')[1];
    if (!(firstPart in rootPaths)) event.request.uri = '/index.html';
    return event.request;
}

将函数与VIEWER_REQUEST 上的 CloudFront 分配 相关联,不要忘记发布它。

【讨论】:

  • 非常感谢您的分享!很有帮助!
【解决方案3】:

在 Origin Response 上运行 Lambda@Edge 函数后运行良好。但是,不要忘记在进行此更改后在 CloudFront 上运行失效。此外,它会节省资金,因为 Lambda 只会在请求发送到 Origin 时执行

【讨论】:

    猜你喜欢
    • 2018-06-17
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2019-07-25
    • 2020-11-21
    • 2023-04-05
    • 2022-01-01
    相关资源
    最近更新 更多