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

Cloudfront and Lambda@Edge - fetch from custom origin depending on user agent

我正在通过将我的 JavaScript 应用程序 (SPA) 上传到 S3(默认根目录 object index.html 和 Cache-Control:max-age= 0,no-cache,指向带指纹的 js/css 资产)并将其配置为 CloudFront 分配的来源。我的域名,比方说 SomeMusicPlatform.com 在 Route53 中有一个 CNAME 条目包含分布 URL。这很好用,所有内容都缓存得很好。

现在我想为机器人和社交网络爬虫提供预呈现的 HTML 版本。我已经设置了一个服务器,它在域 prerendered.SomeMusicPlatform.com.[= 中响应 JavaScript 应用程序 (SPA) 的 pre-rendered 版本。 17=]

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

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

问题是带有 Lambda@Edge 函数的 Origin-Request 触发器没有触发,因为 CloudFront 仍然有默认根 Object index.html 缓存并倾向于 return来自缓存边缘的内容。我通过同时使用 SomeMusicPlatform.com/?prerendered=trueSomeMusicPlatform.com 获得 X-Cache:RefreshHit from cloudfront,即使在默认根 Object - index.html.[= 上有一个 Cache-Control:max-age=0, no-cache 17=]

如何使用 CloudFront 保持我的 JavaScript SPA 的 well-cached 服务和低延迟,并从我的自定义预呈现服务器添加服务内容,仅供爬虫机器人使用?

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

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