我需要为URI生成一个href。除了需要百分比编码的保留字符之外,所有这些都很简单,例如,指向/some/path;element的链接应该显示为<a href="/some/path%3Belement"> (我知道path;element代表一个实体)。
起初,我在寻找一个这样做的Java库,但最后我自己写了一些东西(下面看看Java失败的原因,因为这个问题不是特定于Java的)。
因此,RFC 3986 建议什么时候不要编码。正如我所读到的,当字符属于unreserved (ALPHA / DIGIT / "-" / "." / "_" / "~")类时,应该会发生这种情况。到目前一切尚好。但相反的情况呢?RFC只提到百分比(%)总是需要编码。但其他人呢?
问题:是否正确地假定不是无保留的所有事物都可以/应该是百分比编码的?例如,开始括号(不一定需要编码,但分号;需要编码。如果我不对它进行编码,我最终会在跟踪/first时查找<a href="/first;second"> *。但是在<a href="/first(second">之后,我总是像预期的那样寻找/first(second。让我困惑的是,就RFC而言,(和;都在同一个sub-delims类中。正如我想象的那样,无保留地编码任何东西都是一个安全的选择,但是当谈到本地化URI时,SEOability (用户友好)又如何呢?
现在,Java库失败了。我试过这样做
new java.net.URI("http", "site", "/pa;th", null).toASCIISTring()
但这给了http://site/pa;th,这是不好的。观察到的类似结果如下:
javax.ws.rs.core.UriBuilderencodePath(String, String)和encodePathSegment(String, String)* /first是在服务器端单击<a href="/first;second">时调用HttpServletRequest.getServletPath()的结果
编辑:我可能需要提到,这种行为是在Tomcat下观察到的,我检查了Tomcat 6和7的行为都是一样的。
发布于 2011-05-06 16:12:49
绝对路径部分的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 = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="pchar包含子分隔符,这样您就不必在路径部分::@-._~!$&'()*+,;=中对其中的任何部分进行编码。
我编写了http://illegalargumentexception.blogspot.com/2009/12/java-safe-character-handling-and-url.html#URI2009_RESOURCES,其中包括路径的编码器--和往常一样,警告接收者。
发布于 2011-05-16 13:10:53
假设不是无保留的一切都可以/应该是百分比编码,这是正确的吗?
不是的。RFC 3986说:
在正常情况下,URI中的八进制被编码的唯一时间是在从其组件部分生成URI的过程中。实现确定哪些保留字符用作子组件分隔符,哪些可以安全地用作数据。
其含义是根据上下文决定需要对哪些分隔符(即<delimiter>字符)进行编码。那些不需要编码的不应该被编码。
例如,如果/出现在path组件中,则不应该对它进行百分比编码,但是当它出现在查询或片段中时,您应该对它进行百分比编码。
因此,实际上,;字符(它是<reserved>的成员)不应该自动编码百分比。实际上,java和URI类不会这样做;关于如何处理<path>组件,请参阅<path>,特别是步骤7)。
本款加强了这一点:
“保留字符的目的是提供一组分隔字符,这些字符与URI中的其他数据不同。URI的不同之处在于将保留字符替换为其对应的百分比编码的八进制是不等价的。百分比--编码保留字符,或解码与保留字符对应的百分比编码八进制--将改变大多数应用程序对URI的解释方式。因此,保留集中的字符受到保护,因此可以安全地被特定方案和生产者特定的算法用于分隔URI中的数据子组件。”
因此,这表明包含百分比编码的;的URL与包含原始;的URL不一样。最后一句暗示它们不应该是自动编码或解码的百分比。
这就给我们留下了一个问题--为什么要对;进行百分比编码?
假设您有一个CMS,人们可以在其中创建具有任意路径的任意页面。稍后,我需要生成指向所有页面的href链接,例如站点地图组件。因此,我需要一个算法来知道要转义的字符。在这种情况下,分号必须按字面处理,并且应该被转义。
对不起,但分号不应该被转义。
就URL / URI规范而言,;没有特殊的含义。对于特定的web服务器/网站,它可能有特殊的含义,但是在一般的(即没有具体的站点知识)您没有办法知道这一点。
;在特定的URI中确实有特殊的意义,那么如果您对它进行了%-转义,那么您就打破了这个意义。例如,如果站点使用;允许将会话令牌附加到路径,那么百分比编码将阻止它识别会话令牌.;只是某个客户端提供的数据字符,那么如果您对它进行了百分比编码,则可能会更改URI的含义。这是否重要取决于服务器所做的事情;即是否作为应用程序逻辑的一部分进行解码。这意味着知道“应该做的正确的事情”,这就需要深入了解URI对最终用户和/或站点意味着什么。这需要先进的读心术技术来实现。我的建议是让CMS通过适当地转义URI路径的任何分隔符来解决这个问题,然后再将URI路径交付给您的软件。算法是,必然是特定于CMS和内容发布平台的。它/它们将响应由URL标识的文件请求,并需要知道如何解释它们。
(支持任意使用任意路径的人有点疯狂。一定有一些限制。例如,即使是Windows,也不允许在文件名组件中使用文件分隔符。所以你必须在某个地方有一些界限。这只是一个决定他们应该在哪里的问题。)
https://stackoverflow.com/questions/5913623
复制相似问题