冒号是不是需要在 URI 查询参数中进行编码?

Posted

技术标签:

【中文标题】冒号是不是需要在 URI 查询参数中进行编码?【英文标题】:Do colons require encoding in URI query parameters?冒号是否需要在 URI 查询参数中进行编码? 【发布时间】:2012-11-22 17:08:50 【问题描述】:

我注意到 Java 的 UriBuilder 没有对包含在我的查询参数值(ISO 8601 格式的字符串)中的 : 字符进行编码。

根据***,似乎应该对冒号进行编码。

特别是,编码查询字符串使用以下规则:

字母(A-Z 和 a-z)、数字 (0-9) 和字符 '.'、'-'、'~' 和 '_' 保持原样 SPACE 编码为“+”或 %20[需要引用] 所有其他字符编码为 %FF 十六进制表示,任何非 ASCII 字符首先编码为 UTF-8(或其他指定的 编码)

那么,交易是什么?查询参数中的冒号是否应该编码?


更新:

我查看了 URI 语法规范 (RFC 3986),看起来确实不需要在查询参数中编码冒号。这是 URI 的 ABNF 的摘录:

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=

【问题讨论】:

如果我错了,请纠正我,但根据您的链接“:”是保留的 gen-delim 并且“任何 [gen-delim] 也在保留集中被“保留”用作组件内的子组件分隔符”(即子分隔符) 我只是在解释 ABNF,它允许 ':' 作为查询字符串的一部分。这也与 Java 的 UriBuilder 的行为以及我在 .NET 上测试的一些代码相匹配。尽管如此,当您指出文本表明它应该以不同的方式执行时,这仍然令人困惑。 【参考方案1】:

是的,它们应该被编码在查询字符串中。正确的编码是%3A

但是,我可以理解为什么 UriBuilder 不编码 :。您不希望在绝对 URI 中的协议之后(例如 http:)或用户名和密码之间(例如 ftp://username:password@domain.com)对冒号进行编码。

【讨论】:

谢谢,恩里科。似乎来源冲突。虽然***(和其他地方)说它们应该被编码,但如果你查看 URI 语法规范中的 ABNF,它们似乎没有。查看我的答案的更新。 这在技术上是不正确的。在查询中允许使用冒号。看。 ***.com/a/5330261/125562【参考方案2】:

Java SDK 中没有UriBuilder,它是由 JAX-RS 定义的。 documentation 声明查询参数应该是 URL 编码的,其他组件使用 RFC 3986 编码。

构建器方法执行相应 URI 组件中不允许的字符的上下文编码,遵循 application/x-www-form-urlencoded 媒体类型用于查询参数和 RFC 3986 用于所有其他组件的规则

但是,JAX-RS 的 Jersey 实现不符合此规范,并根据 RFC 3986 对所有内容进行编码。这是一个错误,请参阅JIRA ticket。

【讨论】:

有趣的是,UriBuilder.queryParam(name, value) 这两种方法似乎与UriBuilder.replaceQuery(query) 有不同的编码规则。前者编码':' 字符,而后者没有,至少在RESTEasy 3.0.7.Final 中是这样。这是预期的行为吗?您是否解释了为什么存在差异?

以上是关于冒号是不是需要在 URI 查询参数中进行编码?的主要内容,如果未能解决你的问题,请参考以下文章

如何编码 URI 参数值?

Fetch 记录

JS中编码和解码的总结

Nuxt 使用双冒号编码/解码 URI

我是不是需要在 ajax 请求和接收该请求的 php 之间编码/解码查询参数?

URL编码