将 CloudFront 配置为代理查询字符串作为 S3 对象键的一部分?
Configure CloudFront to proxy query string as part of S3 object key?
我们将 AWS CloudFront 配置为将请求代理到 S3 存储桶。
AWS CloudFront 允许您对其进行配置,以便查询字符串参数也被代理到原始服务器 (docs) - 我们也进行了此配置。
我遇到的问题是查询字符串参数似乎没有包含在 S3 对象键查找中。
例如,我们有像这样的对象键:
foo
foo?a=1
foo?b=2
但是如果我们发出像 https://cf-distro-url.com/foo?a=1 or https://cf-distro-url.com/foo?b=2 这样的请求,我们实际上会得到 /foo
内容而不是特定的关键内容。
看起来 CloudFront 可能正在代理查询字符串参数,但它们并未用作 S3 对象键查找过程的一部分。
有没有人遇到过这种情况? and/or知道解决方案吗?
谢谢!
使用 Web 浏览器,如果直接访问 CloudFront 和 S3,都不会像您期望的那样在对象键中使用 ?
,因为未转义的 ?
是分隔符对于 HTTP 中的查询字符串。
根据定义,?
标志着路径的结束,因此也是对象键的结束。
获取密钥中带有 ?
的对象的唯一方法是 浏览器 发送带有 ?
转义为 %3F
,这意味着 URL 最初必须以这种方式呈现给浏览器。
您不能将键名称中带有 ?
的对象上传到 S3,然后使用 URL 中的文字 ?
从浏览器访问它。
使用 curl
进行了演示,但浏览器行为相同。
在 URI 中使用 /foo?bar
:
$ curl -v 'http://.....s3.amazonaws.com/foo?bar=1'
* About to connect() to .....s3.amazonaws.com port 80 (#0)
* Trying x.x.x.x... connected
> GET /foo?bar=1 HTTP/1.1
< HTTP/1.1 404 Not Found
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>foo</Key> <<< requested object is "foo"
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
在 URI 中使用 /foo%3Fbar=1
:
$ curl -v 'http://.....s3.amazonaws.com/foo%3Fbar=1'
* About to connect() to .....s3.amazonaws.com port 80 (#0)
* Trying x.x.x.x... connected
> GET /foo%3Fbar=1 HTTP/1.1
< HTTP/1.1 404 Not Found
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>foo?bar=1</Key> <<< requested object is "foo?bar=1"
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
这是 URL 形成方式的限制,而不是在 S3(或 CloudFront)中...但在 S3 文档中提到:
The following characters in a key name may require additional code handling and will likely need to be URL encoded or referenced as HEX
...
Question mark ("?")
http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#object-keys
如果您能够使用 SDK 正确上传此类对象,那么它正在为您转义字符。 Web 浏览器不会隐式地这样做,因为 ?
具有特定的含义。
无论 CloudFront 是否将查询字符串传递给 S3,网络行为都是相同的——查询字符串不是键的一部分。
看起来您发送的方式是由 CloudFront 翻译的。您需要像下面这样查询对象
您需要对这些字符执行 URI 编码,以便将它们作为对象名称传递给 S3。
希望对您有所帮助。
我们将 AWS CloudFront 配置为将请求代理到 S3 存储桶。
AWS CloudFront 允许您对其进行配置,以便查询字符串参数也被代理到原始服务器 (docs) - 我们也进行了此配置。
我遇到的问题是查询字符串参数似乎没有包含在 S3 对象键查找中。
例如,我们有像这样的对象键:
foo
foo?a=1
foo?b=2
但是如果我们发出像 https://cf-distro-url.com/foo?a=1 or https://cf-distro-url.com/foo?b=2 这样的请求,我们实际上会得到 /foo
内容而不是特定的关键内容。
看起来 CloudFront 可能正在代理查询字符串参数,但它们并未用作 S3 对象键查找过程的一部分。
有没有人遇到过这种情况? and/or知道解决方案吗?
谢谢!
使用 Web 浏览器,如果直接访问 CloudFront 和 S3,都不会像您期望的那样在对象键中使用 ?
,因为未转义的 ?
是分隔符对于 HTTP 中的查询字符串。
根据定义,?
标志着路径的结束,因此也是对象键的结束。
获取密钥中带有 ?
的对象的唯一方法是 浏览器 发送带有 ?
转义为 %3F
,这意味着 URL 最初必须以这种方式呈现给浏览器。
您不能将键名称中带有 ?
的对象上传到 S3,然后使用 URL 中的文字 ?
从浏览器访问它。
使用 curl
进行了演示,但浏览器行为相同。
在 URI 中使用 /foo?bar
:
$ curl -v 'http://.....s3.amazonaws.com/foo?bar=1'
* About to connect() to .....s3.amazonaws.com port 80 (#0)
* Trying x.x.x.x... connected
> GET /foo?bar=1 HTTP/1.1
< HTTP/1.1 404 Not Found
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>foo</Key> <<< requested object is "foo"
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
在 URI 中使用 /foo%3Fbar=1
:
$ curl -v 'http://.....s3.amazonaws.com/foo%3Fbar=1'
* About to connect() to .....s3.amazonaws.com port 80 (#0)
* Trying x.x.x.x... connected
> GET /foo%3Fbar=1 HTTP/1.1
< HTTP/1.1 404 Not Found
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>foo?bar=1</Key> <<< requested object is "foo?bar=1"
<RequestId>...</RequestId>
<HostId>...</HostId>
</Error>
这是 URL 形成方式的限制,而不是在 S3(或 CloudFront)中...但在 S3 文档中提到:
The following characters in a key name may require additional code handling and will likely need to be URL encoded or referenced as HEX
...
Question mark ("?")
http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#object-keys
如果您能够使用 SDK 正确上传此类对象,那么它正在为您转义字符。 Web 浏览器不会隐式地这样做,因为 ?
具有特定的含义。
无论 CloudFront 是否将查询字符串传递给 S3,网络行为都是相同的——查询字符串不是键的一部分。
看起来您发送的方式是由 CloudFront 翻译的。您需要像下面这样查询对象
您需要对这些字符执行 URI 编码,以便将它们作为对象名称传递给 S3。
希望对您有所帮助。