RFC3986 - 哪些pchars需要进行百分比编码?

min*_*das 10 java language-agnostic rfc rfc3986

我需要生成href一个URI.当涉及需要百分比编码的保留字符时,一切都很简单,例如链接/some/path;element应该显示为<a href="/some/path%3Belement">(我知道它path;element代表一个单独的实体).

最初我正在寻找一个可以做到这一点的Java库,但我最终自己写了一些东西(请看下面的Java失败,因为这个问题不是特定于Java的).

因此,RFC 3986 确实建议何时不进行编码.正如我所读到的,当角色属于unreserved (ALPHA / DIGIT / "-" / "." / "_" / "~")阶级时,这应该发生.到现在为止还挺好.但是相反的情况呢?RFC只提到percent(%)总是需要编码.但其他人呢?

问题:假设所有非保留的,可以/应该是百分比编码是正确的吗?例如,开括号(不一定需要编码,但分号;可以.如果我不对其进行编码,我最终会在关注/first时寻找*<a href="/first;second">.但是<a href="/first(second">我总是/first(second按照预期最终寻找.是什么让我困惑的是,双方(;在同一个sub-delims类尽可能RFC去.正如我想象的那样,对非保留的所有内容进行编码是一个安全的选择,但是当涉及到本地化的URI时,SEOability,用户友好性呢?

现在,Java库失败了.我试过这样做,
new java.net.URI("http", "site", "/pa;th", null).toASCIISTring()
但这给了http://site/pa;th不好的.观察到的类似结果:

  • javax.ws.rs.core.UriBuilder
  • Spring的UriUtils -我曾经尝试都encodePath(String, String)encodePathSegment(String, String)

[*] /firstHttpServletRequest.getServletPath()点击时在服务器端调用的结果<a href="/first;second">

编辑:我可能需要提到在Tomcat下观察到这种行为,我已经检查过Tomcat 6和7的行为方式相同.

Ste*_*n C 5

假设不是未保留的所有内容都可以/应该进行百分比编码是否正确?

不。RFC 3986 是这样说的:

“在正常情况下,URI 中的八位字节被百分比编码的唯一时间是在从其组件部分生成 URI 的过程中。这是当实现确定哪些保留字符将用作子组件分隔符以及哪些可以安全地用作数据。”

这意味着您<delimiter>可以根据上下文决定需要对哪些定界符(即字符)进行编码。那些不需要编码的不应该被编码。

例如,/如果a出现在路径组件中,您不应该对其进行百分比编码,但是当它出现在查询或片段中时,您应该对其进行百分比编码。

所以,事实上,一个;字符(它是 的成员不<reserved>应该被自动百分比编码。实际上 java URL 和 URI 类不会这样做;请参阅URI(...) javadoc,特别是第 7 步)了解如何的<path>部件进行处理。

本段加强了这一点:

“保留字符的目的是提供一组定界字符,这些字符可与 URI 中的其他数据区分开来。在用相应的百分比编码八位字节替换保留字符方面不同的 URI 是不等价的。百分比编码保留字符,或解码与保留字符相对应的百分比编码的八位字节,将改变大多数应用程序解释 URI 的方式。因此,保留集中的字符不受规范化保护,因此可以安全地由特定方案和用于在 URI 中分隔数据子组件的特定于生产者的算法。”

所以这表示包含百分比编码;的 URL 与包含原始;. 最后一句暗示它们不应该被百分比编码或自动解码。


这给我们留下了一个问题 - 为什么 ;进行百分比编码?

假设您有一个 CMS,人们可以在其中创建具有任意路径的任意页面。稍后,我需要生成指向所有页面的 href 链接,例如站点地图组件。因此我需要一个算法来知道要转义哪些字符。在这种情况下,分号必须按字面意思处理并且应该转义。

对不起,但这并不意味着分号应该被转义。

就 URL / URI 规范而言,;没有特殊含义。它可能对特定的 Web 服务器/网站具有特殊意义,但一般而言(即没有该站点的特定知识)您无法知道这一点。

  • 如果;确实在特定 URI 中具有特殊含义,那么如果您对其进行百分比转义,那么您就破坏了该含义。例如,如果站点使用;允许将会话令牌附加到路径,那么百分比编码将阻止它识别会话令牌......

  • 如果;只是某个客户端提供的数据字符,那么如果您对其进行百分比编码,则可能会改变 URI 的含义。这是否重要取决于服务器做什么;即是否解码作为应用程序逻辑的一部分。

这意味着知道“正确的事情要做”需要深入了解 URI 对最终用户和/或站点意味着什么。这需要先进的读心技术来实现。我的建议是让 CMS 解决它,方法是在将 URI 路径传送到您的软件之前,适当地转义 URI 路径的任何分隔符。该算法必须特定于 CMS 和内容交付平台。它/他们将响应对 URL 标识的文档的请求,并且需要知道如何解释它们。

(支持使用任意路径的任意人有点疯狂。必须有一些限制。例如,即使 Windows 也不允许您在文件名组件中使用文件分隔符。因此您将不得不在某处设置一些边界。它只是决定他们应该在哪里的问题。)


McD*_*ell 2

绝对路径部分的ABNF

 path-absolute = "/" [ segment-nz *( "/" segment ) ]
 segment       = *pchar
 segment-nz    = 1*pchar
 pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 pct-encoded   = "%" HEXDIG HEXDIG
 unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 reserved      = gen-delims / sub-delims
 sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
               / "*" / "+" / "," / ";" / "="
Run Code Online (Sandbox Code Playgroud)

pchar包含子分隔符,因此您不必在路径部分中对其中任何一个进行编码::@-._~!$&'()*+,;=

我编写了自己的 URL 生成器,其中包含路径编码器 - 一如既往,买者自负。