一、概述
HTTP 的請(qǐng)求報(bào)文
GET 方法的特點(diǎn)
POST 方法的特點(diǎn)
GET 和 POST 的區(qū)別
二、HTTP 的請(qǐng)求報(bào)文
首先我們要解決的第一個(gè)問(wèn)題是:GET 和 POST 是什么?
GET 和 POST 其實(shí)都是 HTTP 的請(qǐng)求方法。除了這 2 個(gè)請(qǐng)求方法之外,HTTP 還有 HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS 這 6 個(gè)請(qǐng)求方法。所以HTTP 的請(qǐng)求方法共計(jì)有 8 種,它們的描述如下所示:
接下來(lái)我們解決第二個(gè)問(wèn)題:請(qǐng)求方法如何使用?
要解決這個(gè)問(wèn)題,我們首先需要了解 HTTP 的請(qǐng)求報(bào)文結(jié)構(gòu):
可以看到 HTTP 的請(qǐng)求報(bào)文由三部分構(gòu)成:
- 請(qǐng)求行:由請(qǐng)求方法(Method)、URL 字段和 HTTP 的協(xié)議版本組成,注意其中的空格、回車符和換行符均不可省略,所以我們的請(qǐng)求方法實(shí)際上就是位于請(qǐng)求行中的了。
- 請(qǐng)求頭部:位于請(qǐng)求行之后,個(gè)數(shù)可以為 0~若干個(gè),每個(gè)請(qǐng)求頭部都包含一個(gè)頭部字段名和一個(gè)值,它們之間用冒號(hào) ":" 分隔,在最后用回車符和換行符表示結(jié)束。
- 請(qǐng)求數(shù)據(jù):如果請(qǐng)求方法為 GET,那么請(qǐng)求數(shù)據(jù)為空。它主要是在 POST 中進(jìn)行使用,適用于需要填表單(FORM)的場(chǎng)景。
我們通過(guò)一個(gè)實(shí)際的例子來(lái)看看 HTTP 的 GET 請(qǐng)求報(bào)文是什么樣的,我們這里以訪問(wèn)
https://api.github.com/search/users?q=JakeWharton 為例,通過(guò)抓包我們得到的請(qǐng)求報(bào)文如下所示:
GET /search/users?q=JakeWharton HTTP/1.1
Host: api.github.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _octo=GH1.1.1623908978.1549006668; _ga=GA1.2.548087391.1549006688; logged_in=yes; dotcom_user=GoMarck; _gid=GA1.2.17634150.1554639136; _gat=1
我們重點(diǎn)看到請(qǐng)求行:
GET /search/users?q=JakeWharton HTTP/1.1
可以看到請(qǐng)求方法用的是 GET 請(qǐng)求,URL為 /search/users?q=JakeWharton,協(xié)議為 HTTP1.1。
請(qǐng)求行下面部分全都是請(qǐng)求頭部,我們可以看到 host 為 api.github.com,連接方式為長(zhǎng)連接等信息。值得注意的是我們這個(gè)例子中是不存在請(qǐng)求數(shù)據(jù)的。
接下來(lái)我們?cè)趤?lái)看一下 POST 請(qǐng)求的報(bào)文(該例子源自其他博客):
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
可以看到請(qǐng)求行中請(qǐng)求方法為 POST,URL 為空,協(xié)議版本也是 HTTP1.1。它和上面 GET 方法例子不一樣的地方在于它的請(qǐng)求參數(shù)是位于請(qǐng)求數(shù)據(jù)中的,可以看到 name=Professional%20Ajax&publisher=Wiley 就是它的請(qǐng)求數(shù)據(jù)。并且我們要注意到在請(qǐng)求數(shù)據(jù)和請(qǐng)求頭之間是空出一行的,這是必不可少的。
三、GET 方法的特點(diǎn)
1、前面的例子:
https://api.github.com/search/users?q=JakeWharton 就是一個(gè)非常典型的 GET 請(qǐng)求的表現(xiàn)形式,即請(qǐng)求的數(shù)據(jù)會(huì)附在 URL 之后(放在請(qǐng)求行中),以 ? 分割 URL 和傳輸數(shù)據(jù),多個(gè)參數(shù)用 & 連接。
2、除此之外,根據(jù) HTTP 規(guī)范,GET 用于信息獲取,而且應(yīng)該是安全和冪等的 。
安全性指的是非修改信息,即該操作用于獲取信息而非修改信息。換句話說(shuō),GET請(qǐng)求一般不應(yīng)產(chǎn)生副作用,也就是說(shuō),它僅僅是獲取資源信息,就像數(shù)據(jù)庫(kù)查詢一樣,不會(huì)修改,增加數(shù)據(jù),不會(huì)影響資源的狀態(tài)。
冪等性 (Idempotence) 則指的是無(wú)論調(diào)用這個(gè)URL 多少次,都不會(huì)有不同的結(jié)果的 HTTP 方法。而在實(shí)際過(guò)程中,這個(gè)規(guī)定沒(méi)有那么嚴(yán)格。例如在一個(gè)新聞應(yīng)用中,新聞?wù)军c(diǎn)的頭版不斷更新,雖然第二次請(qǐng)求會(huì)返回不同的一批新聞,該操作仍然被認(rèn)為是安全的和冪等的,因?yàn)樗偸欠祷禺?dāng)前的新聞。
3、GET 是會(huì)被瀏覽器主動(dòng)緩存的,如果下一次傳輸?shù)臄?shù)據(jù)相同,那么就會(huì)返回緩存中的內(nèi)容,以求更快地展示數(shù)據(jù)。
4、GET 方法的 URL 一般都具有長(zhǎng)度限制,但是需要注意的是 HTTP 協(xié)議中并未規(guī)定 GET 請(qǐng)求的長(zhǎng)度。這個(gè)長(zhǎng)度限制主要是由瀏覽器和 Web 服務(wù)器所決定的,并且各個(gè)瀏覽器對(duì)長(zhǎng)度的限制也各不相同。
5、GET 方法只產(chǎn)生一個(gè) TCP 數(shù)據(jù)包,瀏覽器會(huì)把請(qǐng)求頭和請(qǐng)求數(shù)據(jù)一并發(fā)送出去,服務(wù)器響應(yīng) 200 ok(返回?cái)?shù)據(jù))。
四、POST 方法的特點(diǎn)
- 根據(jù) HTTP 規(guī)范,POST 表示可能修改變服務(wù)器上的資源的請(qǐng)求。例如我們?cè)谒⒅醯臅r(shí)候?qū)δ称恼逻M(jìn)行點(diǎn)贊,就是提交的 POST 請(qǐng)求,因?yàn)樗淖兞朔?wù)器中的數(shù)據(jù)(該篇文章的點(diǎn)贊數(shù))。
- POST 方法因?yàn)橛锌赡苄薷姆?wù)器上的資源,所以它是不符合安全和冪等性的。
- 從前面關(guān)于 POST 的請(qǐng)求報(bào)文也可以看出,POST 是將請(qǐng)求信息放置在請(qǐng)求數(shù)據(jù)中的,這也是 POST 和 GET 的一點(diǎn)不那么重要的區(qū)別。有一些博客的說(shuō)法是 GET 請(qǐng)求的請(qǐng)求信息是放置在 URL 的而 POST 是放置在請(qǐng)求數(shù)據(jù)中的所以 POST 比 GET 更安全。其實(shí)這種說(shuō)法很有問(wèn)題,隨便抓下包 POST 中的請(qǐng)求報(bào)文就暴露無(wú)疑了,這又何來(lái)安全之說(shuō)?
- 因?yàn)?POST 方法的請(qǐng)求信息是放置在請(qǐng)求數(shù)據(jù)中的,所以它的請(qǐng)求信息是沒(méi)有長(zhǎng)度限制的。
- POST 方法會(huì)產(chǎn)生兩個(gè) TCP 數(shù)據(jù)包,瀏覽器會(huì)先將請(qǐng)求頭發(fā)送給服務(wù)器,待服務(wù)器響應(yīng)100 continue,瀏覽器再發(fā)送請(qǐng)求數(shù)據(jù),服務(wù)器響應(yīng)200 ok(返回?cái)?shù)據(jù))。這么看起來(lái) GET 請(qǐng)求的傳輸會(huì)比 POST 快上一些(因?yàn)镚ET 方法只發(fā)送一個(gè) TCP 數(shù)據(jù)包),但是實(shí)際上在網(wǎng)絡(luò)良好的情況下它們的傳輸速度基本相同。
五、GET 和 POST 的區(qū)別
上面說(shuō)了那么多 GET 方法和 POST 方法各自的特點(diǎn),它們?cè)谕庠诘谋憩F(xiàn)上似乎是有著諸多的不同,但是實(shí)際上,它們的本質(zhì)是一樣的,并無(wú)區(qū)別?。。?/p>
這似乎有些不可思議,但是我們重新回想一下 GET 和 POST 是什么?它們是 HTTP 請(qǐng)求協(xié)議的請(qǐng)求方法,而 HTTP 又是基于TCP/IP的關(guān)于數(shù)據(jù)如何在萬(wàn)維網(wǎng)中如何通信的協(xié)議,所以 GET/POST 實(shí)際上都是 TCP 鏈接。
也就是說(shuō),GET 和 POST 所做的事其實(shí)是一樣的,如果你給 GET 加上請(qǐng)求數(shù)據(jù),給 POST 加上 URL 參數(shù),這在技術(shù)上是完全可行的,事實(shí)上確實(shí)有一些人為了貪圖方便在更新資源時(shí)用了GET,因?yàn)橛肞OST必須要到FORM(表單),這樣會(huì)麻煩一點(diǎn)(但是強(qiáng)烈不建議這樣子做?。。。?。
既然 GET 和 POST 的底層都是 TCP,那么為什么 HTTP 還要特別將它們區(qū)分出來(lái)呢?
其實(shí)可以想象一下,如果我們直接使用 TCP 進(jìn)行數(shù)據(jù)的傳輸,那么無(wú)論是單純獲取資源的請(qǐng)求還是修改服務(wù)器資源的請(qǐng)求在外觀上看起來(lái)都是 TCP 鏈接,這樣就非常不利于進(jìn)行管理。所以在 HTTP 協(xié)議中,就會(huì)對(duì)這些不同的請(qǐng)求設(shè)置不同的類別進(jìn)行管理,例如單純獲取資源的請(qǐng)求就規(guī)定為 GET、修改服務(wù)器資源的請(qǐng)求就規(guī)定為 POST,并且也對(duì)它們的請(qǐng)求報(bào)文的格式做出了相應(yīng)的要求(例如請(qǐng)求參數(shù) GET 位于 URL 而 POST 則位于請(qǐng)求數(shù)據(jù)中)。
當(dāng)然,如果我們想將 GET 的請(qǐng)求參數(shù)放置在請(qǐng)求數(shù)據(jù)中或者將 POST 的請(qǐng)求數(shù)據(jù)放置在 URL 中,這是完全可以的,雖然這樣子做并不符合 HTTP 的規(guī)范。但是這樣子做是否能得到我們期望的響應(yīng)數(shù)據(jù)呢?答案是未必,這取決于服務(wù)器的行為。
以 GET 方法在請(qǐng)求數(shù)據(jù)中放置請(qǐng)求參數(shù)為例,有些服務(wù)器會(huì)將請(qǐng)求數(shù)據(jù)中的參數(shù)讀出,在這種情況下我們依然能獲得我們期望的響應(yīng)數(shù)據(jù);而有些服務(wù)器則會(huì)選擇直接忽略,這種情況下我們就無(wú)法獲取期望的響應(yīng)數(shù)據(jù)了。
所以,對(duì)于 GET 和 POST 的區(qū)別,總結(jié)來(lái)說(shuō)就是:它們的本質(zhì)都是 TCP 鏈接,并無(wú)區(qū)別。但是由于 HTTP 的規(guī)定以及瀏覽器/服務(wù)器的限制,導(dǎo)致它們?cè)趹?yīng)用過(guò)程中可能會(huì)有所不同。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7002瀏覽量
88941 -
HTTP
+關(guān)注
關(guān)注
0文章
504瀏覽量
31194 -
瀏覽器
+關(guān)注
關(guān)注
1文章
1022瀏覽量
35330
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論