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

我知道非标准的%uxxxxscheme,但这并不是一个明智的select,因为该scheme已被W3C拒绝。

一些有趣的例子:

心的性格。 如果我在浏览器中input:

http://www.google.com/search?q=♥ 

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

 http://www.google.com/search?q=%E2%99%A5 

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

 urllib.quote_plus(x.encode("latin-1")) '%E2%99%A5' 

这是有道理的,除了不能用Latin-1编码的东西,就像三重点字符。

  

如果我input的url

 http://www.google.com/search?q=… 

进入我的浏览器,然后复制并粘贴,我得到

 http://www.google.com/search?q=%E2%80%A6 

背部。 这似乎是做的结果

 urllib.quote_plus(x.encode("utf-8")) 

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

但是接下来我不清楚浏览器是如何知道是用UTF-8还是用Latin-1来解码。

由于这似乎是模棱两可的:

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

工作,所以我不知道如何浏览器找出是否使用UTF-8或Latin-1解码。

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

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

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

这似乎是因为在过去有其他可接受的URL编码方式,浏览器尝试了一些解码URI的方法,但是如果你是编码人员,你应该使用UTF-8。

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

如果您只是在url栏中input一个url,那么浏览器就没有一个基本网页可供使用,因此只能猜测。 所以在这种情况下,似乎一直在做utf-8(因为你的input都产生了三字节的forms值)。

可悲的事实是,AFAIK没有什么标准来设置查询string中的值是什么字符,或者URL中的任何字符都应该被解释为。 至less在查询string中的值的情况下,没有理由假设它们必然对应于字符。

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

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

IRI不能取代URI,因为在某些情况下,只有URI(有效的,ASCII)是允许的,包括HTTP。

相反,你指定一个IRI,当它走出去的时候它会变成一个URI。

第一个问题是你的需求是什么? 使用廉价的编辑器创build文本和支持各种语言之间的UTF-8编码是一个很好的折衷。 关于识别编码的浏览器,响应(来自Web服务器)应该告诉浏览器编码。 大多数浏览器仍然会尝试猜测,因为在很多情况下,这种情况可能会丢失或者错误。 他们通过阅读一些结果stream猜测是否有一个字符不符合默认编码。 目前所有的浏览器(?我没有检查这个,但它非常接近真实)使用utf-8作为默认。

所以使用utf-8,除非你有一个令人信服的理由来使用其他编码scheme之一。