如何在 S3 和 Cloudfront 托管的静态站点上保留不带尾部斜杠的路由查询参数

Moj*_*wen 2 javascript amazon-s3 static-site amazon-cloudfront

我有一个静态生成的网站,我已将其上传到 S3 并通过 Cloudfront 发行版公开 - 它有一个根index.html文件和几个静态生成的子页面(例如/donate/index.html)。我已将存储桶配置为充当静态主机并index.html作为索引文档。我可以通过直接访问S3前缀来访问这些页面,例如/donate/正确显示/donate/index.html.

问题是 - 当我/donate?some=query&param=here自动链接到 S3 时,302 将这些没有尾部斜杠的页面重定向到带有尾部斜杠的页面,删除了我的客户端 JavaScript 用于轻微跟踪状态的查询参数。

例如,/donate?some=query&param=here302 会/donate/丢失该上下文,这使得人们构建 URL 变得困难,因为他们必须记住包含尾部斜杠(如果您希望网络爬虫记住新路由,则 HTTP 302 也是一个糟糕的 http 响应)。

这是不起作用的:

  • 配置 Cloudfront 以使用分配缓存策略中的查询参数来缓存路由(Cloudfront > 分配 > 行为 > 编辑 > 缓存策略)
  • 配置 Cloudfront 以在分配的源请求策略中转发查询参数(Cloudfront > 分配 > 行为 > 编辑 > 源请求策略)
  • 配置 S3 存储桶以使用 S3 重定向规则重定向路由(S3 > 存储桶 > 属性 > 静态 Web 托管 > 重定向规则)

Moj*_*wen 6

最终破解的方法是:创建一个查看器请求 Cloudfront 函数来手动检查路径是否既不包含文件扩展名也不包含尾部斜杠,并在这些情况下添加一个。

function handler (event) {
    var request = event.request;
    var uri = request.uri;

    if( !uri.includes('.') && !uri.endsWith('/') ) {
        request.uri = uri + '/'
    }

    return request;
};
Run Code Online (Sandbox Code Playgroud)

在 Cloudfront 中创建此函数(Cloudfront > 函数 > 创建函数),然后将其附加到您的分配的行为(Cloudfront > 分配 > 行为 > 编辑 > 查看者请求 > Cloudfront 函数)。

确保在发行版使用新设置完成初始化后使站点失效,并通过 CURL 测试新路由 - 您应该看到以下行为更改:

# BEFORE:
curl -v --location http://example.com/donate?please=keep > /dev/null
> GET /donate?please=keep
> RESP 302
> GET /donate/
> RESP 200

# AFTER
curl -v --location http://example.com/donate?please=keep > /dev/null
> GET /donate?please=keep
> RESP 200
Run Code Online (Sandbox Code Playgroud)

还有别的办法吗?我会后悔为每次 Cloudfront 函数调用付费吗?有没有办法通过纯粹的 Cloudfront 或 S3 策略更改来实现这一点?