HTTP中GET與POST的區(qū)別

作者:楊光鏈接:https://www.zhihu.com/question/28586791/answer/145424285來源:知乎著作權(quán)歸作者所有参淹。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)奕删,非商業(yè)轉(zhuǎn)載請注明出處裳擎。剛好最近比較系統(tǒng)的研究了一下HTTP協(xié)議里GET和POST方法的區(qū)別妒茬,以下內(nèi)容摘抄自我的博客:HTTP協(xié)議中GET和POST方法的區(qū)別 - Sunshinevvv's Blog** ,本文記錄了我的探究歷程慰枕,沒有耐心的童鞋可以直接翻到最后看結(jié)論:語義之爭台汇。
------------------以下是博客正文-----------------
HTTP協(xié)議中GET和POST方法的區(qū)別已經(jīng)是老生常談了,也是面試熱門問題稼钩,我之前對此也只有一個粗淺的印象顾稀,這里來認(rèn)真探討一下。
通常的理解
w3schools關(guān)于這個問題的解答:HTTP 方法:GET 對比 POST** 列出了一般的理解坝撑,比如:

GET后退按鈕/刷新無害静秆,POST數(shù)據(jù)會被重新提交(瀏覽器應(yīng)該告知用戶數(shù)據(jù)會被重新提交)。GET書簽可收藏巡李,POST為書簽不可收藏抚笔。GET能被緩存,POST不能緩存 侨拦。GET編碼類型application/x-www-form-url塔沃,POST編碼類型encodedapplication/x-www-form-urlencoded 或 multipart/form-data。為二進(jìn)制數(shù)據(jù)使用多重編碼阳谍。GET歷史參數(shù)保留在瀏覽器歷史中蛀柴。POST參數(shù)不會保存在瀏覽器歷史中。GET對數(shù)據(jù)長度有限制矫夯,當(dāng)發(fā)送數(shù)據(jù)時鸽疾,GET 方法向 URL 添加數(shù)據(jù);URL 的長度是受限制的(URL 的最大長度是 2048 個字符)训貌。POST無限制制肮。GET只允許 ASCII 字符。POST沒有限制递沪。也允許二進(jìn)制數(shù)據(jù)豺鼻。與 POST 相比,GET 的安全性較差款慨,因為所發(fā)送的數(shù)據(jù)是 URL 的一部分儒飒。在發(fā)送密碼或其他敏感信息時絕不要使用 GET !POST 比 GET 更安全檩奠,因為參數(shù)不會被保存在瀏覽器歷史或 web 服務(wù)器日志中桩了。GET的數(shù)據(jù)在 URL 中對所有人都是可見的。POST的數(shù)據(jù)不會顯示在 URL 中埠戳。

這個對比整體沒什么毛病井誉,但只是給出了一些現(xiàn)象上的區(qū)別,但并沒有解釋為什么整胃,對于這個問題的理解不能就停在這一層颗圣。
理解錯了?
有一篇文章99%的人理解錯 HTTP 中 GET 與 POST 的區(qū)別**,否定了上述回答:“很遺憾在岂,這不是我們要的回答荚藻!”,作者說:
GET和POST本質(zhì)上就是TCP鏈接洁段,并無差別应狱。但是由于HTTP的規(guī)定和瀏覽器/服務(wù)器的限制,導(dǎo)致他們在應(yīng)用過程中體現(xiàn)出一些不同祠丝。 GET和POST還有一個重大區(qū)別疾呻,簡單的說:GET產(chǎn)生一個TCP數(shù)據(jù)包;POST產(chǎn)生兩個TCP數(shù)據(jù)包写半。對于GET方式的請求岸蜗,瀏覽器會把http header和data一并發(fā)送出去,服務(wù)器響應(yīng)200(返回數(shù)據(jù))叠蝇; 而對于POST璃岳,瀏覽器先發(fā)送header,服務(wù)器響應(yīng)100 continue悔捶,瀏覽器再發(fā)送data铃慷,服務(wù)器響應(yīng)200 ok(返回數(shù)據(jù))。
都講到TCP了蜕该,感覺很高大上有木有犁柜,起碼當(dāng)時看到這篇文章的我是信了的。
反轉(zhuǎn)堂淡?馋缅?
但是在逛知乎時又看到了這篇文章:聽說『99% 的人都理解錯了 HTTP 中 GET 與 POST 的區(qū)別』?绢淀?萤悴,指出了前文的兩個錯誤:
100 continue 只有在請求里帶了Expect: 100-continueheader 的時候才有意義。When the request contains an Expect header field that includes a 100-continue expectation, the 100 response indicates that the server wishes to receive the request payload body, as described in Section 5.1.1. The client ought to continue sending the request and discard the 100 response. If the request did not contain an Expect header field containing the 100-continue expectation, the client can simply discard this interim response.

我們通常在討論 GET vs POST 的時候皆的,實(shí)際上討論的是 specification覆履,而不是 implementation。什么是 specification祭务?說白了就是相關(guān)的 RFC内狗。implementation 則是所有實(shí)現(xiàn)了 specification 中描述的代碼/庫/產(chǎn)品,比如 curl义锥,Python 的 requests 庫,或者 Chrome岩灭。POST 請求怎么發(fā)送拌倍,根本就不是這段 RFC 在討論的事情。RFC 中只說明了 100 continue 和 Expect header 的聯(lián)系,比如你想在 GET 請求里帶 body柱恤,一樣可以發(fā)送 Expect: 100-continue 并等待 100 continue数初,這是符合標(biāo)準(zhǔn)的。也就是說梗顺,『XHR 發(fā)送兩個 TCP packets』是關(guān)于 implementation 的知識泡孩,而不是關(guān)于 specification 的知識。你不能說『Chrome 在 AJAX POST 的時候會發(fā)兩個 TCP packets寺谤,GET 只會發(fā)一個』是 GET 和 POST 的區(qū)別仑鸥,正如你不能因為北京 PM 2.5 經(jīng)常爆表就說國家關(guān)于工業(yè)廢氣排放的標(biāo)準(zhǔn)有問題。
說得似乎更有道理变屁,而且也搬出了RFC眼俊,specification,implementation這些高端詞匯粟关,這下子我這個吃瓜群眾再也坐不住了疮胖,決定親自去研究一下。
RFC探秘
首先闷板,什么是RFC呢澎灸?Wiki上面的定義是:
征求意見稿(英語:Request For Comments,縮寫為RFC)遮晚,是由互聯(lián)網(wǎng)工程任務(wù)組(IETF)發(fā)布的一系列備忘錄击孩。文件收集了有關(guān)互聯(lián)網(wǎng)相關(guān)信息,以及UNIX和互聯(lián)網(wǎng)社區(qū)的軟件文件鹏漆,以編號排定巩梢。目前RFC文件是由互聯(lián)網(wǎng)協(xié)會(ISOC)贊助發(fā)行。
簡單理解RFC就是互聯(lián)網(wǎng)的規(guī)范艺玲,我們通常所說的「協(xié)議」就是以RFC的形式存在括蝠,而現(xiàn)行的HTTP/1.1規(guī)范的RFC有如下幾個: RFC7230**RFC7231**饭聚, RFC7232**忌警, RFC7233**RFC7234**秒梳,RFC7235**法绵。 其中RFC7231里的Section 4. Request Methods涉及到了幾個HTTP方法,接下來仔細(xì)閱讀這一章節(jié)酪碘。
The request method token is the primary source of request semantics; it indicates the purpose for which the client has made this request and what is expected by the client as a successful result.
這里牽涉到一個很重要的詞語:semantic 「語義」朋譬,那么什么是語義呢?這一篇文章給出了解釋:語法和語義的區(qū)別**兴垦。
一種語言是合法句子的集合徙赢。什么樣的句子是合法的呢字柠?可以從兩方面來判斷:語法和語義。語法是和文法結(jié)構(gòu)有關(guān)狡赐,然而語義是和按照這個結(jié)構(gòu)所組合的單詞符號的意義有關(guān)窑业。合理的語法結(jié)構(gòu)并不表明語義是合法的。例如我們常說:我上大學(xué)枕屉,這個句子是符合語法規(guī)則的常柄,也符合語義規(guī)則。但是大學(xué)上我搀擂,雖然符合語法規(guī)則西潘,但沒有什么意義,所以說是不符合語義的哥倔。
對于HTTP請求來說秸架,語法是指請求響應(yīng)的格式,比如請求第一行必須是 方法名 URI 協(xié)議/版本 這樣的格式咆蒿,具體內(nèi)容可以參見之前寫的《圖解HTTP》讀書筆記里面的內(nèi)容东抹,凡是符合這個格式的請求都是合法的。
語義則定義了這一類型的請求具有什么樣的性質(zhì)沃测。比如GET的語義就是「獲取資源」缭黔,POST的語義是「處理資源」,那么在具體實(shí)現(xiàn)這兩個方法時蒂破,就必須考慮其語義馏谨,做出符合其語義的行為。
當(dāng)然在符合語法的前提下實(shí)現(xiàn)違背語義的行為也是可以做到的附迷,比如使用GET方法修改用戶信息惧互,POST獲取資源列表,這樣就只能說這個請求是「合法」的喇伯,但不是「符合語義」的喊儡。 寫到這里突然聯(lián)想到XML里面的兩個概念:Well Formed和Valid,似乎也正是語法和語義的理念呢稻据。
上文說到方法是請求語義的主要來源艾猜,也即是還有次要來源,一些請求Header可以進(jìn)一步修飾請求的語義捻悯,比如一個帶上了 Range Header的GET請求就變成了部分請求匆赃。
RFC7231里定義了HTTP方法的幾個性質(zhì):
Safe - 安全這里的「安全」和通常理解的「安全」意義不同,如果一個方法的語義在本質(zhì)上是「只讀」的今缚,那么這個方法就是安全的算柳。客戶端向服務(wù)端的資源發(fā)起的請求如果使用了是安全的方法荚斯,就不應(yīng)該引起服務(wù)端任何的狀態(tài)變化埠居,因此也是無害的查牌。 此RFC定義事期,GET, HEAD, OPTIONS 和 TRACE 這幾個方法是安全的滥壕。但是這個定義只是規(guī)范,并不能保證方法的實(shí)現(xiàn)也是安全的兽泣,服務(wù)端的實(shí)現(xiàn)可能會不符合方法語義绎橘,正如上文說過的使用GET修改用戶信息的情況。引入安全這個概念的目的是為了方便網(wǎng)絡(luò)爬蟲和緩存唠倦,以免調(diào)用或者緩存某些不安全方法時引起某些意外的后果称鳞。User Agent(瀏覽器)應(yīng)該在執(zhí)行安全和不安全方法時做出區(qū)分對待,并給用戶以提示稠鼻。
Idempotent - 冪等冪等的概念是指同一個請求方法執(zhí)行多次和僅執(zhí)行一次的效果完全相同冈止。按照RFC規(guī)范,PUT候齿,DELETE和安全方法都是冪等的熙暴。同樣,這也僅僅是規(guī)范慌盯,服務(wù)端實(shí)現(xiàn)是否冪等是無法確保的周霉。引入冪等主要是為了處理同一個請求重復(fù)發(fā)送的情況,比如在請求響應(yīng)前失去連接亚皂,如果方法是冪等的俱箱,就可以放心地重發(fā)一次請求。這也是瀏覽器在后退/刷新時遇到POST會給用戶提示的原因:POST語義不是冪等的灭必,重復(fù)請求可能會帶來意想不到的后果狞谱。
Cacheable - 可緩存性 顧名思義就是一個方法是否可以被緩存,此RFC里GET禁漓,HEAD和某些情況下的POST都是可緩存的跟衅,但是絕大多數(shù)的瀏覽器的實(shí)現(xiàn)里僅僅支持GET和HEAD。關(guān)于緩存的更多內(nèi)容可以去看RFC7234璃饱。

在這三個特性里一直在強(qiáng)調(diào)同一個事情与斤,那就是協(xié)議不等于實(shí)現(xiàn):協(xié)議規(guī)定安全在實(shí)現(xiàn)里不一定安全,協(xié)議規(guī)定冪等在實(shí)現(xiàn)里不一定冪等荚恶,協(xié)議規(guī)定可緩存在實(shí)現(xiàn)里不一定可緩存撩穿。這其實(shí)就是上面那個作者提到的specification和implementation的關(guān)系。
語義之爭
走到這一步谒撼,其實(shí)就明白了要理解這兩個方法的區(qū)別食寡,本質(zhì)上是 「語義」的對比而不是「語法」的對比,是「Specification」的對比而不是「Implementation」的對比 廓潜。
關(guān)于這兩種方法的語義抵皱,RFC7231里原文已經(jīng)寫得很好了:
The GET method requests transfer of a current selected representation for the target resource. GET is the primary mechanism of information retrieval and the focus of almost all performance optimizations. Hence, when people speak of retrieving some identifiable information via HTTP, they are generally referring to making a GET request.A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

The POST method requests that the target resource process the representation enclosed in the request according to the resource’s own specific semantics.
勉強(qiáng)渣翻一下善榛,再加上點(diǎn)自己的理解:
GET的語義是請求獲取指定的資源。GET方法是安全呻畸、冪等移盆、可緩存的(除非有 Cache-ControlHeader的約束),GET方法的報文主體沒有任何語義。
POST的語義是根據(jù)請求負(fù)荷(報文主體)對指定的資源做出處理伤为,具體的處理方式視資源類型而不同咒循。POST不安全,不冪等绞愚,(大部分實(shí)現(xiàn))不可緩存叙甸。為了針對其不可緩存性,有一系列的方法來進(jìn)行優(yōu)化位衩,以后有機(jī)會再研究(FLAG已經(jīng)立起)裆蒸。
還是舉一個通俗栗子吧,在微博這個場景里糖驴,GET的語義會被用在「看看我的Timeline上最新的20條微博」這樣的場景僚祷,而POST的語義會被用在「發(fā)微博、評論遂赠、點(diǎn)贊」這樣的場景中久妆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跷睦,隨后出現(xiàn)的幾起案子筷弦,更是在濱河造成了極大的恐慌,老刑警劉巖抑诸,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烂琴,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜕乡,警方通過查閱死者的電腦和手機(jī)奸绷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來层玲,“玉大人号醉,你說我怎么就攤上這事⌒量椋” “怎么了畔派?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長润绵。 經(jīng)常有香客問我线椰,道長,這世上最難降的妖魔是什么尘盼? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任憨愉,我火速辦了婚禮烦绳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘配紫。我一直安慰自己径密,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布笨蚁。 她就那樣靜靜地躺著睹晒,像睡著了一般趟庄。 火紅的嫁衣襯著肌膚如雪括细。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天戚啥,我揣著相機(jī)與錄音奋单,去河邊找鬼。 笑死猫十,一個胖子當(dāng)著我的面吹牛览濒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拖云,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贷笛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宙项?” 一聲冷哼從身側(cè)響起乏苦,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尤筐,沒想到半個月后汇荐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盆繁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年掀淘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片油昂。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡革娄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冕碟,到底是詐尸還是另有隱情拦惋,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布鸣哀,位于F島的核電站架忌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏我衬。R本人自食惡果不足惜叹放,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一饰恕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧井仰,春花似錦埋嵌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至合是,卻和暖如春了罪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聪全。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工泊藕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人难礼。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓娃圆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛾茉。 傳聞我的和親對象是個殘疾皇子讼呢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容