对Unicode字符进行URL编码的正确方法是什么?

Jos*_*son 106 unicode urlencode web-standards utf-8 character-encoding

我知道非标准的%uxxxx方案,但这似乎不是明智的选择,因为该方案已被W3C拒绝.

一些有趣的例子:

心中的人物.如果我在浏览器中输入:

http://www.google.com/search?q=?
Run Code Online (Sandbox Code Playgroud)

然后复制并粘贴它,我看到这个URL

http://www.google.com/search?q=%E2%99%A5
Run Code Online (Sandbox Code Playgroud)

这使得它看起来像Firefox(或Safari)正在这样做.

urllib.quote_plus(x.encode("latin-1"))
'%E2%99%A5'
Run Code Online (Sandbox Code Playgroud)

这是有道理的,除了不能用Latin-1编码的东西,比如三点字符.

Run Code Online (Sandbox Code Playgroud)

如果我输入URL

http://www.google.com/search?q=…
Run Code Online (Sandbox Code Playgroud)

进入我的浏览器然后复制粘贴,我明白了

http://www.google.com/search?q=%E2%80%A6
Run Code Online (Sandbox Code Playgroud)

背部.这似乎是做的结果

urllib.quote_plus(x.encode("utf-8"))
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为...不能用Latin-1编码.

但后来我不清楚浏览器是如何用UTF-8或Latin-1解码的.

因为这似乎含糊不清:

In [67]: u"…".encode('utf-8').decode('latin-1')
Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6'
Run Code Online (Sandbox Code Playgroud)

有效,所以我不知道浏览器是如何用UTF-8或Latin-1解码的.

使用我需要处理的特殊字符做什么是正确的?

Joh*_*ker 64

我总是用UTF-8编码.从百分比编码维基百科页面:

通用URI语法要求在URI中提供字符数据表示的新URI方案实际上必须表示来自未保留集的字符而不进行转换,并且应该根据UTF-8将所有其他字符转换为字节,然后百分比编码这些值.此要求于2005年1月随着RFC 3986的出版而引入.在此日期之前引入的URI方案不受影响.

似乎因为过去有其他可接受的URL编码方法,浏览器会尝试几种解码URI的方法,但如果您是进行编码的方法,则应使用UTF-8.

  • 还应该使用UTF-8,因为它是新IRI标准(RFC 3987,http://tools.ietf.org/html/rfc3986)允许替换旧URL标准的唯一编码. (8认同)
  • 如果其他人和我一样惊讶,@ RemyLebeau的评论中的文字提到了RFC3987,但链接是旧的规范3896.正确的URL显然是http://tools.ietf.org/html/rfc3987 (3认同)

ara*_*nid 9

一般规则似乎是浏览器根据表单的内容类型对表单响应进行编码.这是一个猜测,如果服务器发送给我们"text/xml; charset = iso-8859-1",那么他们希望以相同的格式返回响应.

如果您只是在URL栏中输入一个URL,那么浏览器没有可以使用的基页,因此只需要猜测.所以在这种情况下它似乎一直在做utf-8(因为你的输入都产生了三个八位字节的表格值).

可悲的事实是,AFAIK没有标准用于将查询字符串中的值设置为什么字符,或者实际上URL中的任何字符都应该被解释为.至少在查询字符串值的情况下,没有理由认为他们一定对应的字符.

这是,你必须告诉你期望的字符集的查询字符串编码为---例如,在Tomcat中,你必须调用request.setEncoding()(或类似的方法),你的服务器架构的已知问题之前,你调用任何request.getParameter()方法.关于这个主题的文档缺乏可能反映了许多开发人员对该问题缺乏认识.(我经常向Java受访者询问Reader和InputStream之间的区别是什么,并经常看到空白的样子)

  • RFC 3987(http://tools.ietf.org/html/rfc3986)定义了一种标准编码 - 编码不允许未编码的字符时必须使用UTF-8. (6认同)

Rem*_*eau 8

IRI(RFC 3987)是取代URI/URL(RFC 3986及更早版本)标准的最新标准.URI/URL本身不支持Unicode(嗯,RFC 3986增加了对未来基于URI/URL的协议的支持,但不会更新过去的RFC)."%uXXXX"方案是在某些情况下允许Unicode的非标准扩展,但并非每个人都普遍实现.另一方面,IRI完全支持Unicode,并要求在进行百分比编码之前将文本编码为UTF-8.


Mar*_*ham 6

IRI不替换URI,因为在某些上下文中只允许使用URI(实际上是ASCII) - 包括HTTP.

相反,您指定一个IRI,并在线路上转换为URI.