天天看點

程式員:我終于知道post和get的差別

IT界知名的程式員曾說:對于那些月薪三萬以下,自稱IT工程師的碼農們,其實我們從來沒有把他們歸為我們IT工程師的隊伍。他們雖然總是以IT工程師自居,但隻是他們一廂情願罷了。

此話一出,不知激起了多少(碼農)程式員的憤怒,卻又無可奈何,于是碼農問程式員。

碼農:你知道get和post請求到底有什麼差別?

程式員:你看這篇就知道了。

碼農:你月薪三萬了?

程式員:嗯。

碼農:你是怎麼做到的?

程式員:我做夢做到的

前言

這個問題幾乎面試的時候都會問到,是一個老生常談的話題,然而随着不斷的學習,對于以前的認識有很多誤區,是以還是需要不斷地總結的,學而時習之,不亦說乎。

關于get和post如果你有條件上百度的話,至少有200百萬條結果,每個人都有每個人的思考,當然,這篇也是我的思考,如果有些結論有錯誤,希望能夠噴起來。在批評中不斷改進,與諸君共勉一句話:若批評無意義,則贊美無意義。

01 特點

1.1 http的特點

基于tcp/ip、一種網絡應用層協定、超文本傳輸協定HyperText Transfer Protocol

工作方式:用戶端請求服務端應答的模式

快速:無狀态連接配接

靈活:可以傳輸任意對象,對象類型由Content-Type标記

用戶端請求request消息包括以下格式:請求行(request line)、請求頭部(header)、空行、請求資料

服務端響應response也由四個部分組成,分别是:狀态行、消息報頭、空行、響應正文

1.2 請求方法

http請求可以使用多種請求方法。

HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。

HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

HTTP2.0 新的二進制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本協定的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進制則不同,隻認0和1的組合。基于這種考慮HTTP2.0的協定解析決定采用二進制格式,實作友善且健壯。

多路複用(MultiPlexing),即連接配接共享,即每一個request都是是用作連接配接共享機制的。一個request對應一個id,這樣一個連接配接上可以有多個request,每個連接配接的request可以随機的混雜在一起,接收方可以根據request的 id将request再歸屬到各自不同的服務端請求裡面。

header壓縮,如上文中所言,對前面提到過HTTP1.x的header帶有大量資訊,而且每次都要重複發送,HTTP2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重複header的傳輸,又減小了需要傳輸的大小。

服務端推送(server push),同SPDY一樣,HTTP2.0也具有server push功能。

參考連結:https://baike.baidu.com/item/HTTP%202.0/12520156?fr=aladdin

1 GET 請求指定的頁面資訊,并傳回實體主體。

2 HEAD 類似于get請求,隻不過傳回的響應中沒有具體的内容,用于擷取報頭

3 POST 向指定資源送出資料進行處理請求(例如送出表單或者上傳檔案)。資料被包含在請求體中。POST請求可能會導緻新的資源的建立和/或已有資源的修改。

4 PUT 從用戶端向伺服器傳送的資料取代指定的文檔的内容。

5 DELETE 請求伺服器删除指定的頁面。

6 CONNECT HTTP/1.1協定中預留給能夠将連接配接改為管道方式的代理伺服器。

7 OPTIONS 允許用戶端檢視伺服器的性能。

8 TRACE 回顯伺服器收到的請求,主要用于測試或診斷。

1.3 我們耳熟能詳的的差別

http協定最常見的兩種方法GET和POST,這幾點答案其實有幾點并不準确

請求緩存:GET 會被緩存,而post不會

收藏書簽:GET可以,而POST不能

保留浏覽器曆史記錄:GET可以,而POST不能

用處:get常用于取回資料,post用于送出資料

安全性:post比get安全

請求參數:querystring 是url的一部分get、post都可以帶上。 get的querystring(僅支援urlencode編碼),post的參數是放在body(支援多種編碼)

請求參數長度限制:get請求長度最多1024kb,post對請求資料沒有限制

02 常見的誤區

get和post誤區

針對上面常見的差別,如果面試的時候這麼說,肯定是有很大的毛病,剛在學校面試的時候也曾經囫囵吞棗地這樣說過,現在回過頭再想以前的錯誤認知,又有許多新的認識。

2.1 誤區一

“用處:get常用于取回資料,post用于送出資料”

曾聽到過這樣一種說法:get替換post來優化網站性能,雖然這種說法沒錯,也的确get常被用于取回資料,但是post也被一些ui架構使用于取回資料,比如kendo ui中的grid,就是用post來接受資料的。是以結論是get、post用途也是因地制宜。如果你有使用過kendo UI,會發現分頁、過濾、自定義的參數都包含在form data裡面。

請求參數

get是querystring(僅支援urlencode編碼),post是放在body(支援多種編碼)

query參數是URL的一部分,而GET、POST等是請求方法的一種,不管是哪種請求方法,都必須有URL,而URL的query是可選的,可有可無。

2.2 誤區二

“請求參數長度限制:get請求長度最多1024kb,post對請求資料沒有限制”

這句話看上去實在沒毛病啊,菜鳥教程也是這樣說的啊。雖然字面意思上沒有錯誤,但是了解一定要正确。我想說的是GET方法送出的url參數資料大小沒有限制,在http協定中沒有對url長度進行限制(不僅僅是querystring的長度),這個限制是特定的浏覽器及伺服器對他的限制

下面就是對各種浏覽器和伺服器的最大處理能力做一些說明

IE浏覽器對URL的最大限制為2083個字元

Firefox (Browser):對于Firefox浏覽器URL的長度限制為65,536個字元。

Safari (Browser):URL最大長度限制為 80,000個字元。

Opera (Browser):URL最大長度限制為190,000個字元。

Google (chrome):URL最大長度限制為8182個字元。

Apache (Server):能接受最大url長度為8,192個字元。

Microsoft Internet Information Server(IIS):能接受最大url的長度為16,384個字元。

是以為了符合所有标準,url的最好不好超過最低标準的2083個字元(2k+35)。當然在做用戶端程式時,url并不展示給使用者,隻是個程式調用,這時長度隻收web伺服器的影響了。對于中文的傳遞,一個漢字最終編碼後的字元長度是9個字元。

最常見的form表單,浏覽器預設的form表單,預設的content-type是application/x-www-form-urlencoded,送出的資料會按照key value的方式,jquery的ajax預設的也是這種content-type。當然在post方式中添加querystring一定是可以接收的到,但是在get方式中加body參數就不一定能成功接收到了。

2.3 誤區三

“post比get安全性要高”

這裡的安全是相對性,并不是真正意義上的安全,通過get送出的資料都将顯示到url上,頁面會被浏覽器緩存,其他人檢視曆史記錄會看到送出的資料,而post不會。另外get送出資料還可能會造成CSRF攻擊。

2.4 誤區四:“GET産生一個TCP資料包;POST産生兩個TCP資料包。”

這一點了解起來還是有一定難度的,實際上,不論哪一種浏覽器,在發送 POST 的時候都沒有帶 Expect 頭,server 也自然不會發 100 continue。通過抓包發現,盡管會分兩次,body 就是緊随在 header 後面發送的,根本不存在『等待伺服器響應』這一說。

從另一個角度說,TCP 是傳輸層協定。别人問你應用層協定裡的 GET 和 POST 有啥差別,你回答說這倆在傳輸層上發送資料的時候不一樣,确定别人不抽你?

參考資料:https://zhuanlan.zhihu.com/p/25028045

3 http狀态碼附錄

3.1 狀态碼1xx

100 Continue:

伺服器僅接收到部分請求,但是一旦伺服器并沒有拒絕該請求,用戶端應該繼續發送其餘的請求。

101 Switching Protocols:

伺服器轉換協定:伺服器将遵從客戶的請求轉換到另外一種協定。

102: 由WebDAV(RFC 2518):

擴充的狀态碼,代表處理将被繼續執行

3.2 狀态碼2xx:成功

200 OK:

請求成功(其後是對GET和POST請求的應答文檔。)

201 Created:

請求被建立完成,同時新的資源被建立。

202 Accepted:

供處理的請求已被接受,但是處理未完成。

203 Non-authoritative Information:

文檔已經正常地傳回,但一些應答頭可能不正确,因為使用的是文檔的拷貝。

204 No Content:

沒有新文檔。浏覽器應該繼續顯示原來的文檔。如果使用者定期地重新整理頁面,而Servlet可以确定使用者文檔足夠新,這個狀态代碼是很有用的。

205 Reset Content:

沒有新文檔。但浏覽器應該重置它所顯示的内容。用來強制浏覽器清除表單輸入内容。

206 Partial Content:

客戶發送了一個帶有Range頭的GET請求,伺服器完成了它。

3.3 狀态碼3xx:重定向

300 Multiple Choices:

多重選擇。連結清單。使用者可以選擇某連結到達目的地。最多允許五個位址。

301 Moved Permanently:

所請求的頁面已經轉移至新的url

302 Found:

所請求的頁面已經臨時轉移至新的url。

303 See Other:

所請求的頁面可在别的url下被找到。

304 Not Modified:

未按預期修改文檔。用戶端有緩沖的文檔并發出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶隻想比指定日期更新的文檔)。伺服器告訴客戶,原來緩沖的文檔還可以繼續使用。

305 Use Proxy:

客戶請求的文檔應該通過Location頭所指明的代理伺服器提取。

306 Unused:

此代碼被用于前一版本。目前已不再使用,但是代碼依然被保留。

307 Temporary Redirect:

被請求的頁面已經臨時移至新的url。

3.4 狀态碼4xx:用戶端錯誤

400 Bad Request:

伺服器未能了解請求。

401 Unauthorized:

被請求的頁面需要使用者名和密碼。

401.1:

登入失敗。

401.2:

伺服器配置導緻登入失敗。

401.3:

由于 ACL 對資源的限制而未獲得授權。

401.4:

篩選器授權失敗。

401.5:

ISAPI/CGI 應用程式授權失敗。

401.7:

通路被 Web 伺服器上的 URL 授權政策拒絕。這個錯誤代碼為 IIS 6.0 所專用。

402 Payment Required:

此代碼尚無法使用。

403 Forbidden:

對被請求頁面的通路被禁止。

404 Not Found:

伺服器無法找到被請求的頁面。

405 Method Not Allowed:

請求中指定的方法不被允許。

406 Not Acceptable:

伺服器生成的響應無法被用戶端所接受。

407 Proxy Authentication Required:

使用者必須首先使用代理伺服器進行驗證,這樣請求才會被處理。

408 Request Timeout:

請求超出了伺服器的等待時間。

409 Conflict:

由于沖突,請求無法被完成。

410 Gone:

被請求的頁面不可用。

411 Length Required:

“Content-Length” 未被定義。如果無此内容,伺服器不會接受請求。

412 Precondition Failed:

請求中的前提條件被伺服器評估為失敗。

413 Request Entity Too Large:

由于所請求的實體的太大,伺服器不會接受請求。

414 Request-url Too Long:

由于url太長,伺服器不會接受請求。當post請求被轉換為帶有很長的查詢資訊的get請求時,就會發生這種情況。

415 Unsupported Media Type:

由于媒介類型不被支援,伺服器不會接受請求。

416 Requested Range Not Satisfiable:

伺服器不能滿足客戶在請求中指定的Range頭。

417 Expectation Failed:

執行失敗。

423:

鎖定的錯誤。

3.5 狀态碼5** 服務端錯誤

500 Internal Server Error:

請求未完成。伺服器遇到不可預知的情況。

501 Not Implemented:

請求未完成。伺服器不支援所請求的功能。

502 Bad Gateway:

請求未完成。伺服器從上遊伺服器收到一個無效的響應。

503 Service Unavailable:

請求未完成。伺服器臨時過載或當機。

504 Gateway Timeout:

網關逾時。

505 HTTP Version Not Supported:

伺服器不支援請求中指明的HTTP協定版本。

————————————————

版權聲明:本文為CSDN部落客「dotnet全棧開發」的原創文章,遵循 CC 4.0 BY-SA 版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/kebi007/article/details/103059900

程式員:我終于知道post和get的差別