首页 > 解决方案 > Cloudfront 错误页面上未调用 Lambda@Edge 函数

问题描述

我通过 Cloudfront 在 S3 存储桶上提供 Angular 应用程序的静态文件。我的 Cloudfront 发行版设置了错误页面,因此它仍然呈现 Angular 的 index.html。这意味着如果我请求<cloudfront-distribution>.cloudfront.net/home-page,而不是说它没有找到home-page在 S3 存储桶上命名的文件,它仍然会呈现 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@ 注入的响应标头边缘功能。问题是当访问与S3存储桶中的文件不对应的路由时。如果我访问<cloudfront-distribution>.cloudfront.net/home-page,S3将返回404,Cloudfront将处理404并根据错误页面配置采取行动,即响应使用 200 状态代码并渲染 index.html 文件。发生这种情况时,我看不到通过 Lambda@Edge 函数注入的任何标头,而我的 Angular 应用程序的所有其他脚本文件都有标头。

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

标签: angularamazon-web-servicesamazon-s3amazon-cloudfrontaws-lambda-edge

解决方案


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

虽然当前的答案对于这个问题绝对是正确的,但我还有另一个可能有助于讨论的约束:

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

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

选项 #1 - 切换到 Origin Request 事件

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

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

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

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

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

推荐阅读