amazon-s3 - Cloudfront 和 Lambda@Edge - 根据用户代理从自定义来源获取

标签 amazon-s3 aws-lambda amazon-cloudfront

我通过将我的 JavaScript 应用程序 (SPA) 上传到 S3(默认根对象 index.html 和 Cache-Control:max-age=0,无缓存,指向指纹 js/css Assets )并将其配置为一个源到 CloudFront 分配。我的域名,比如说 SomeMusicPlatform.com 在 Route53 中有一个包含分发 URL 的 CNAME 条目。这很好用,并且都很好地缓存。

现在我想为机器人和社交网络爬虫提供一个预渲染的 HTML 版本。我已经设置了一个服务器,该服务器在域 处响应 JavaScript 应用程序 (SPA) 的预渲染版本。 prerendered.SomeMusicPlatform.com .

我在 lambda 函数中尝试做的是检测用户代理,识别机器人并为它们提供来自我的自定义服务器的预渲染版本(而不是我通常为常规浏览器提供的来自 S3 的 JavaScript 内容)。

我想我可以通过使用 Lambda@Edge: Using an Origin-Request Trigger to Change From an Amazon S3 Origin to a Custom Origin 来实现这一点。函数将源切换到我的自定义预渲染服务器,以防它在响应 header 中识别爬虫机器人(或者,在测试阶段,使用 prerendered=true 查询参数)。

问题是带有 Lambda@Edge 函数的 Origin-Request 触发器没有触发,因为 CloudFront 仍然具有默认根对象 index.html缓存并倾向于从缓存边缘返回内容。我收到 X-Cache:RefreshHit from cloudfront通过同时使用 SomeMusicPlatform.com/?prerendered=trueSomeMusicPlatform.com ,即使有 Cache-Control:max-age=0, no-cache在默认根对象 - index.html 上。

如何使用 CloudFront 保持 JavaScript SPA 的良好缓存服务和低延迟,并为爬虫机器人添加来自自定义预渲染服务器的服务内容?

最佳答案

通过添加 mywebsite.com/?prerendered=true 解决了缓存问题(使用 mywebsite.comprerendered 时获得相同的命中)到 cloudfront 分发中的查询白名单。这意味着 CloudFront 现在可以正确维护网站内容的正常版本和预渲染版本,具体取决于参数的存在(不提供来自 S3 源的参数缓存内容,以及来自我的自定义源的参数缓存内容在 lambda 函数中指定送达)。

这对于测试阶段来说已经足够了 - 以确保机制正常工作。然后我按照 Michael 的建议在 Viewer Request 触发器中添加了另一个 lambda 函数,它添加了一个自定义 header Is-Bot如果在 User-Agent 中检测到机器人.同样,需要白名单,这一次是针对自定义 header (根据自定义 header 维护两个源的缓存)。源请求触发器中稍后的另一个 lambda 函数然后决定使用哪个源,具体取决于 Is-Bot标题。

关于amazon-s3 - Cloudfront 和 Lambda@Edge - 根据用户代理从自定义来源获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47517987/

相关文章:

java - 在 Amazon s3 中下载批量对象

amazon-web-services - ELK堆栈(Elasticsearch,Logstash,Kibana)-logstash是必需的组件吗?

node.js - AWS SQS+Lambda,我应该删除消息吗? NodeJS

caching - 如何预热CloudFront边缘服务器的缓存?

amazon-s3 - 何时创建 S3 存储桶

ruby-on-rails - 将静态 JSON 数据导出到 Amazon S3 并通过 AJAX 检索它

node.js - 如何使用 AWS Lambda 中的完整请求 URL 仅在某些页面上执行逻辑

node.js - 使用 AWS SDK 为事件桥规则添加 AWS Lambda 作为目标

duplicates - Cloudfront 自定义源导致重复内容问题

amazon-s3 - Cloudfront在访问索引文档时给出 "Access denied"