日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

http request乱码的真相

發布時間:2025/3/21 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 http request乱码的真相 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先,從瀏覽器端看下有多少種情況:

1.在瀏覽器的地址欄,或者搜索框里輸入地址:http://www.test.com/衣服/search?keyword=T恤

2.在一個指定了編碼的網頁中,提交一個form,如:

1 2 3 4 5 6 7 8 9 10 11 12 <html>? <head>? ????<meta charset="gbk">? </head>? <body>? <p>你好</p>? <form id="productSearchForm" action="http://127.0.0.1:8080/test.html" method="post">? ????<input name="keyword" class="keyword" value="T恤" maxlength="30">? ????<button type="submit">搜索</button>? </form>? </body>? </html>

當然還有,各種細分的選項,如get/post,form里是否指定了編碼。

3. ajax請求里的編碼。

我們從流程上來看,一個http request要經過哪些東東的處理:

1.瀏覽器/JavaScript

2.web server,以tomcat/jetty為例

3.filter/servlet ,以Java為例

4.web 框架,以spring?mvc為例。

對于在瀏覽器的地址欄支持輸入的地址,各種瀏覽器是如何處理的,可以參考這個:

http://www.ruanyifeng.com/blog/2010/02/url_encoding.html

也可以自己簡單的測試,在Linux下執行:

1 nc -l 8080

接著在瀏覽器里直接訪問 http://localhost:8080/衣服/search?keyword=T恤,

然后在就可以看到nc的輸出結果了。當然,瀏覽器的debug工具也可以很方法地看到編碼的結果,不過用nc,就不用自己跑一個web服務器了,非常方便。

另外那個keyword=T恤,也是有意選擇的,這樣可以很方便地看到編碼的結果。恤的gbk編碼是兩個byte,utf-8編碼是3個byte,也很容易區別到底是什么編碼。

簡單地總結下對于瀏覽器地址欄里直接訪問:http://www.test.com/衣服/search?keyword=T恤 ?的編碼情況:

對于chrome,“衣服”和“T恤”都是utf-8編碼;

對于IE8,“衣服”和“T恤”都是gbk編碼。

這里實際上有兩個概念,一個是URI的編碼,一個是query string(即?后面的字符串)的編碼。

http request里的Content-Type設置:

http request是可以指定request的編碼信息的,如:

1 Content-Type: application/x-www-form-urlencoded ; charset=UTF-8
但實際上,瀏覽器都沒有這樣提供這樣的說明……

form提交里的編碼設置:

form可以這樣子設置編碼:

1 <form accept-charset="UTF-8" enctype="application/x-www-form-urlencoded;charset=UTF-8"

但是實際上瀏覽器卻不一定會這么做……

比如,把頁頁編碼設置為gbk,再把form編碼設置為utf-8。

簡單測試,IE8仍然把form編碼為gbk,chrome雖然編碼為utf-8,但卻沒有在request里指明。。

當然,還有一個小技巧可以強行使用某種編碼,那就是我們先自己轉換好編碼,如:

1 <form id="productSearchForm" action="http://127.0.0.1:8080/%A3%A4"

不過,這樣意義不大。

web server是如何處理http request的編碼的?

只討論tomcat和jetty。

Tomcat對于URI的編碼,有兩個參數可以配置:

URIEncoding:這個可以強制指定用什么編碼處理URI,默認是ISO-8859-1;

useBodyEncodingForURI:這個是一個兼容性比較好的選項,如果在request指定了編碼,則采用request里指定的編碼。因此,設置了這個選項為true之后,在java代碼里就可以調用request.setCharacterEncoding來設置編碼了。

參考:http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q2

Jetty只提供了對query string的編碼的指定方式,沒有提供對URI編碼的設置。因此,對于http:www.test.com/衣服/abcd/ 這樣的URI,jetty總是把“/衣服/abcd/”當做是utf-8編碼。

參考:http://wiki.eclipse.org/Jetty/Howto/International_Characters#International_characters_in_URLs

Spring mvc是如何處理編碼的:

spring mvc里提供了一個Filter:

1 2 3 4 5 6 7 8 9 10 11 12 <filter>? ????<filter-name>encodingFilter</filter-name>? ????<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>? ????<init-param>? ????????<param-name>encoding</param-name>? ????????<param-value>UTF-8</param-value>? ????</init-param>? ????<init-param>? ????????<param-name>forceEncoding</param-name>? ????????<param-value>true</param-value>? ????</init-param>? </filter>

到源代碼里看一下,可以發現,其實里面只是設置了request的encoding:

1 2 3 4 5 6 if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {? ????request.setCharacterEncoding(this.encoding);? ????if (this.forceEncoding) {? ????????response.setCharacterEncoding(this.encoding);? ????}? }

但是這個對request URI的編碼實際上是不起效的。

再看下源代碼里是通過j2ee里的request的API來得到的:

RequestParamMethodArgumentResolver類里:

1 2 3 4 5 6 7 8 protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {? if (arg == null) {? String[] paramValues = webRequest.getParameterValues(name);? if (paramValues != null) {? arg = paramValues.length == 1 ? paramValues[0] : paramValues;? }? }

最終實際上調用的是底層web server的request實現類,如tomcat的是org.apache.catalina.connector.RequestFacade,而web server到底是怎么處理請求的編碼的,參照上一小節。

http request 編碼自動識別

這個比較少用到,只有搜索引擎需要識別這種情況。因為搜索引擎需要處理在地址欄里直接輸入的字符串的編碼。

我測試了google, 百度,淘寶的搜索引擎,都能自動識別編碼。但是其它的一些非搜索引擎的應用,都不能自動識別編碼。

當然,程序員通常只保證在自家的網頁上,點擊的產生的http request能正確地被編碼,被識別。

那么,假定我們現在要做一個搜索類的功能,而且要能自動識別編碼,要怎么處理?

以tomcat為例,首先要配置URIEncoding為ISO-8859-1,這樣保證信息不丟失。

接著,寫一個filter,從request里拿到uri,再進行編碼識別,轉換。編碼識別的庫參考:

https://code.google.com/p/juniversalchardet/

還有另外一個思路,寫一個nginx的插件,先在nginx層識別,轉換好編碼。當然原理都是一樣的。

其它的一些東東:

中文域名的的編碼:

這東東應該沒多少人用吧。不過在jetty的網頁里看到了一些有用的信息:

http://wiki.eclipse.org/Jetty/Howto/International_Characters#International_characters_in_domain_names

瀏覽器實際上會用一個叫Punycode的編碼,把域名轉換成ascii-only的域名,再發起請求。

我測試了下,在chrome里輸入:導航.中國

實際是轉到下面這個域名去了:http://xn--fet810g.xn--fiqs8s

C/C++里的編碼:

我們在源文件test.c里寫上:

printf(“%s”, “中文”);

那么它在源文件test.c里是什么編碼?在編繹出來的test.out/test.exe里是什么編碼?運行時輸出到屏幕(shell/cmd)上又是什么編碼?

其實Python也有這種蛋疼的情況……

QQ在User-Agent里的信息:

用IE8測試時,很神奇地發現在request里發現了QQDownload的字樣,真是相當的令人無語。。

User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; QQDownload 751)

總結:

想要實現 www.test.com/王小明/文章 ?這種url是很困難的,因為你不但要應對各種瀏覽器的編碼,還要處理各種web服務器的不同情況。

出現亂碼時,首先區分request傳過來的是什么編碼,然后response返回的是什么編碼,再逐一排查。

編碼問題可以說是程序員無法回避的問題,我相信即使是很有經驗的程序員,也會被坑。沒有辦法,現實世界就是這么坑爹,只能尋根溯源,一一排查了。

對于程序員通常,只要保證下面幾點就沒有問題了:

  • 指定網頁的編碼;
  • 配置web server對uri使用request里配置的編碼;
  • 在ajax請求里先encodeURI();
  • 在web server端對request設置utf-8編碼,對于response設置utf-8編碼。
from:?http://blog.csdn.net/hengyunabc/article/details/17053585

總結

以上是生活随笔為你收集整理的http request乱码的真相的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。