更新:更好地收集了我的想法
我在查看器请求 Lambda 中为每个用户生成一个唯一标识符 (UUID),然后根据该 UUID 选择要返回的缓存页面。这行得通。
理想情况下,该用户将始终具有相同的 UUID。
如果该查看器请求的 cookie 中不存在该 UUID,我必须在查看器请求中生成该 UUID 。我还需要将该 UUID 设置为 cookie,这当然发生在响应而不是请求中。
如果没有缓存,我的服务器只需处理一个自定义标头并在响应标头中创建一个 Set-Cookie。
如果我想缓存页面,我找不到处理这个问题的方法。我可以忽略缓存的请求标头并提供正确的缓存页面,但随后用户不会保留该 UUID,因为没有设置 cookie 用于他们的下一个请求。
有没有人完成过这样的事情?
我正在尝试的事情
我正在处理几个角度,但还没有开始工作:
我不知道 Cloudfront 中的某种设置会处理从查看器请求到查看器响应的标头或其他数据传递,这可以在 Cloudfront 中的第二个 lambda 中使用。
在查看器请求中抢先修改响应对象标头。我认为这是不可能的,因为它们返回的标头尚未创建,除非我缺少一些内置的 Cloudfront 方法。
某种现有的传递标头,我不知道这是否是一回事,因为我对请求-响应处理的这方面并不十分熟悉,但值得一试。
可能(虽然还没有尝试过)我可以在客户端请求 lambda 中创建整个响应对象,并以某种方式从那里提供缓存页面,修改响应标头然后将其传递给回调方法。
托宾的回答确实有效,但不是一个可靠的解决方案。如果用户没有存储或提供他们的 cookie,它就会变成一个无限循环,而且如果我可以避免的话,我宁愿不要在我的所有页面前面抛出一个重定向
有点工作的概念
- 查看器请求 Lambda,当 UUID 不存在于 cookie 中时,生成 UUID
- 查看器请求 Lambda 在请求对象的标头上的 cookie 中设置 UUID。传入更新请求对象的回调
- UUID cookie 的存在会破坏 Cloudfront 缓存
- 原始请求 Lambda 在存在 UUID 的情况下触发
- 原始请求 Lambda 通过
http.get
设置 UUID cookie 再次调用原始请求 URL(40KB 限制使得在查看器请求 Lambda 中执行此操作不切实际) - Viewer Request Lambda 的第二种情况,看到 UUID 现在存在,剥离 UUID cookie 然后正常继续请求
- 第二个源请求(如果尚未缓存) - 如果缓存了缓存响应,因为缓存破坏 UUID 不存在 - 将实际页面 HTML 返回到第一个源请求
- First Origin Request 收到来自
http.get
包含 HTML 的响应 - First Origin Request 创建自定义响应对象,其中包含响应正文
http.get
和 Set-Cookie 标头设置为我们的原始 UUID
已设置 UUID 的后续调用将从 cookie 中删除 UUID(以防止缓存破坏)并直接跳到 Viewer Request Lambda 中的第二个场景,这将直接加载页面的缓存版本。
我说“有点”是因为当我尝试访问我的端点时,我下载了一个二进制文件。
编辑
这是因为我没有设置content-type
标题。我现在只有一个 302 重定向问题......如果我克服了这个问题,我会发布一个完整的答案。
原始问题
我在查看器请求上有一个函数,它选择一个选项并在从缓存或服务器检索请求之前在请求中设置一些内容。
这行得通,但我希望它为未来的用户记住这个选择。这个想法是简单地设置一个cookie,我可以在下次用户访问时读取。由于这是在查看器请求而不是查看器响应上,我还没有弄清楚如何实现这一点,或者甚至可以通过 Lambda 本身实现。
Viewer Request ->
Lambda picks options (needs to set cookie) ->
gets corresponding content ->
returns to Viewer with set-cookie header intact
我已经看过这些示例,并且能够通过 Lambda 在查看器响应中成功设置 cookie。这对我没有多大帮助,因为需要根据请求做出决定。毫不奇怪,将此代码添加到查看器请求中不会在响应中显示任何内容。