`
chen_gengjia
  • 浏览: 108280 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

细谈 URL 编码

阅读更多

原创,欢迎转载,请标明来源:http://chen-gengjia.iteye.com/blog/969979

 

当我们用百度搜索的时候,在搜索框打入中文关键字,但地址栏的搜索词却变成了%xx 的形式,用谷歌搜索,虽然地址栏关键词还是我们打入的,但复制出来看看,是不是变了呢?再对比一下同样的中文在百度和谷歌下变成的百分号串是不是一样?很明显,浏览器发出搜索请求时,对关键词进行了编码,而且百度谷歌的编码还是不一样的。


事实上,WEB客户端和服务端的数据交换之中,要进行多次编码,具体编码的方式与浏览器及其设置、服务端设置、页面设置都有关系,大家肯定有一个疑惑,对这么一个基本的功能,为什么没有标准呢?请看


混乱的编码:http://www.uedmagazine.com/ued/index.php?entry=entry100217-213747


看了上面这篇,是不是有点清晰又有点混乱呢?說实话,这篇帖子半好半坏,总结一下它给出的知识:


1. 百度搜索框发送请求时,中文(事实上只要是非保留字符都会被编码,这是RFC规定的)会被编码成 gb2312的百分号码,而谷歌会将中文编码为utf-8的百分号码发送,这样就解释了为什么同样的文字关键词地址栏会不宜样,因为他们页面设置的编码是不一样的,查看百度源代码可见 meta 标签规定了 charset="gb2312",谷歌的看不出来,但测试发现应该是utf-8


2.如果不是通过搜索栏的form提交请求,而是直接在地址栏中将关键词部分写上一个中文,发现百度和谷歌一样是 utf-8 百分号编码,(ff 地址栏看不出来,因为它显示的时候自动做了一次 decode,需要复制出来再看),初步结论是,直接通过URL请求时的编码是受本地操作系统默认编码决定的,因为在百度页面查看ff的编码显示是 gbk,但实际复制出来的编码还是 utf-8


这第二点的发现就可以解释为什么服务端在做链接到其他页面时,url string 需要做统一的编码,如 php 的 urlencode 或者 python 的 urllib.quote ,因为如果你直接将中文参数接在URL string 上,由于客户端的操作系统/浏览器配置不一样,它发出请求时做的编码就不一样,这样,服务端新页面接受参数时很有可能出现乱码!也就是說,在服务端用 urlencode 等编码函数编码链接参数,实际上是帮浏览器做了工作,从而消除不同浏览器工作标准不同带来的麻烦。


3. 如果用经过一定编码的字符作为搜索关键词会产生什么后果?百度实验结果发现,搜索框提交经过gb2312编码的关键字,结果不能匹配,比如‘大学’的gb2312编码是 ‘%B4%F3%D1%A7’,(可以在第一次提交搜索请求时在地址栏复制),将%B4%F3%D1%A7放到搜索栏提交,返回结果跟‘大学’没关系(此时地址栏关键字是%25B4%25F3%25D1%25A7)。如果将%B4%F3%D1%A7放到URL里直接提交呢?呵呵,肯定返回正确结果了,因为相当于我们人工帮浏览器做了编码,浏览器没有发现非保留字符就直接提交了。前面說了直接在URL打入中文提交会根据操作系统(本机是utf-8去做编码),那么意味着百度服务端对 gb2312 和 utf-8 两种百分号编码都支持,我们直接在URL中将关键词替换为 “%E5%A4%A7%E5%AD%A6”(大学的utf-8编码),结果不出所料,返回正常。对谷歌的测试差不多。这样,前面那篇文章关于百度不支持 utf-8 的说法显然已经过时了。


关于浏览器发送数据时的编码,请看


http://web.nchu.edu.tw/~jlu/classes/xml/ajax/urlencoding.shtml

http://web.nchu.edu.tw/~jlu/classes/xml/ajax/urlencoding2.shtml

http://web.nchu.edu.tw/~jlu/classes/xml/ajax/urlencoding3.shtml

http://web.nchu.edu.tw/~jlu/classes/xml/ajax/urlencoding4.shtml


上面四篇写得非常好,基本上能将编码问题理解清楚,我们总结一下,编码的不一致有两个维度,第一是浏览器的区别;第二是发送点的区别;两个维度下各种比较,请看

 

http://blog.csdn.net/wangjun_1218/archive/2009/07/08/4330244.aspx


1. form 表单的情况,所有浏览器都是根据meta编码,所以只要整个网站设定统一的页面编码就可以解决

2.ajax发送数据的情况,不同浏览器方案不同,最好先用javascript编码函数做处理 ,最推荐用的是 encodeURIComponent ,关于 javascript的编码,请看

 

http://xkr.us/articles/javascript/encode-compare/   ,

 

其思路跟服务端方案是一致的,发送 ajax 前,先同一对数据进行编码而不是直接发送中文等非保留字符,这样浏览器就不用再去编码(因为不会受不同主机和浏览器的不同而导致发送到服务端的编码不一致),服务端就可以用统一的解码方式去处理用户数据

3. 链接发送参数数据,ff会做一个urlcode(根据内码编码后再用百分号的形式组织),ie直接根据内码发送,不同客户端系统的内码又有可能不一样,所以服务端应该用urlencode等函数做统一编码,具体见上面

4.直接地址栏发送请求,同3,ff 会做一个urlencode,ie 直接根据内码发送

 

 

 

根据上面粗略的说明,之所以要使用javascript 的 encodeURIComponent 和 php 的 urlencode 等客户端/服务端编码函数,原因主要是浏览器厂商的不兼容导致的,虽然有了同一的RFC标准,但是人家不遵守我们小小的 web开发人员又能奈何,只能利用服务端语言提供的编码函数或客户端脚本提供的编码函数,在需要两端交互数据时做必要的编码,让我们用程序语言替浏览器把这分活干了,免得不同浏览器打架,所谓编码,其实就是这么回事

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics