面試官常常會問到的一個問題就是:GET請求和POST請求的區別。因為一個看似簡單的問題就能考察出面試者對網絡協議和通信的掌握程度以及對前后端開發基礎知識是否了解、安全性意識是否足夠強,以及綜合分析與總結能力等。
所以答的好可以讓面試官對你刮目相看,答不好很可能馬上就被面試官心里pass掉了。
所以接下來我們就來好好回答一下這個問題!!
1.瀏覽器回退表現不同:GET在瀏覽器回退時是無害的,而POST會再次提交請求。
當我們在瀏覽器中使用GET方法進行頁面請求時,瀏覽器會將請求參數附加到URL的查詢字符串中,并通過HTTP協議發送給服務器。由于GET是一種冪等的操作,即多次執行同一個GET請求不會產生副作用或改變服務器狀態。
因此當我們點擊瀏覽器的回退按鈕后重新加載之前訪問過的頁面時,瀏覽器會自動從緩存中獲取該頁面并顯示出來。
相反地,當我們使用POST方法提交表單數據或執行某些非冪等操作時,瀏覽器會將請求參數包含在HTTP請求體中,并發送給服務器。POST可能導致對服務器狀態進行更改、資源創建、更新或刪除等重要操作。
因此,在當我們點擊回退按鈕返回到之前訪問過的頁面時,瀏覽器默認行為是再次向服務器發送相同的POST請求以保證執行那個特定操作。
當然這種區別是由瀏覽器和HTTP規范所決定的默認行為。但我們需要注意的是,并非所有情況下都遵循這樣的原則。具體而言:
- GET 請求也可以被緩存起來,取決于 HTTP 響應頭部設置。
- 在 POST 請求上添加合適響應頭(例如 Cache-Control: no-store)可以阻止其被緩存。
- JavaScript 或其他客戶端腳本可以修改默認行為并控制如何處理歷史記錄和回退按鈕事件。
2.GET產生的URL地址可以被Bookmark(即書簽保存),而POST不可以。
當我們使用GET發送請求時,所有的參數都會附加在URL后面,并以鍵值對形式進行傳遞。例如:
http://example.com/page?param1=value1¶m2=value2
這意味著瀏覽器中會顯示的完整URL,URL中包含了全部的參數信息,因此我們可以將該URL添加到書簽或者通過復制粘貼方式共享給其他人。
相比之下,當我們使用POST請求時,參數數據并沒有直接附加在URL上。相反,在HTTP消息體中以表單形式發送給服務器。由于POST請求不會把參數暴露在URL上,所以無法直接被我們保存為書簽。
雖然POST不能直接請求保存為書簽,但仍然有一些其他的方法來共享一個包含POST請求的鏈接。我們可以通過電子郵件、即時通訊應用程序等手段將鏈接分享給他人,并且他們可以點擊該鏈接打開頁面并進行相關操作。
3.瀏覽器對請求地址的處理不同:GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
當瀏覽器發送GET請求時,如果該請求的URL和參數與之前已經訪問過的URL和參數相匹配,則瀏覽器會嘗試從本地緩存獲取響應結果。
這是因為GET請求通常被認為是無副作用(不改變服務器狀態或資源)且冪等(多次執行產生同樣結果)的操作。
由于冪等性,瀏覽器認為可以安全地使用上次獲取到的響應結果,并避免再次向服務器發起請求。
相反,當瀏覽器發送POST請求時,默認情況下不會將其結果緩存。
這是因為POST通常具有副作用(可能會更改服務器狀態或資源),而且不具備冪等性。如果每次都直接使用緩存結果,則可能導致數據不一致或意外操作。
然而,在某些特殊情況下我們希望能夠對POST請求進行緩存以提高性能或減少網絡流量消耗。
在這種情況下, 我們可以通過設置 Cache-Control 和 Expires 等HTTP頭字段來告訴瀏覽器是否可以對POST響應進行緩存,并指定有效期限。
例如:
POST /api/submit HTTP/1.1
Host: example.com
Cache-Control: max-age=3600
在上面這個例子中,通過設置 Cache-Control
為 max-age=3600
,我們告訴瀏覽器可以將該POST請求的響應結果緩存,并且有效期限是3600秒
。
需要注意的是,雖然可以手動設置POST請求進行緩存,但仍需謹慎使用。
因為對于具有副作用和非冪等性的操作,默認不進行緩存是出于安全和數據一致性方面的考慮。
如果確實需要對特定類型的POST請求進行緩存,我們需要確保了解其影響,并在設計時考慮清楚相關風險與利益。
4.編碼方式不同:GET請求只能進行url編碼,而POST支持多種編碼方式。
我們在使用GET請求時會將參數附加到URL的查詢字符串中,以便將其發送給服務器。
GET請求會把參數進行URL編碼(也稱為百分號編碼或URL轉義),以確保特殊字符不會干擾URL結構。以及URL編碼會使用%符號后跟兩個十六進制數字來表示非ASCII字符或某些特殊字符。
例如
GET /search?query=hello%20world HTTP/1.1
Host: example.com
hello world這個查詢詞被進行了URL編碼(%20代表空格)并作為參數傳遞給服務器。
POST請求:
POST請求將數據作為消息正文發送到服務器,并且我們可以使用多種不同的數據編碼方式來對消息體進行格式化。
最常用的POST數據編碼方式是 application/x-www-form-urlencoded ,它與GET相似,也會對非ASCII字符和特殊字符進行URL編碼。
這種方式下,參數按照鍵值對形式出現在消息正文中,并用&符號連接起來。
POST /submit HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencodedname=John+Doe&age=25
5.瀏覽器對響應的處理不同:GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留。
當我們使用GET請求時,參數會附加在URL的查詢字符串中,并顯示在瀏覽器地址欄中。例如:
https://example.com/search?q=keyword
這意味著GET請求的參數將作為查詢字符串一部分出現在URL上。
由于瀏覽器通常會將訪問過的網址保存到歷史記錄中,因此包含參數的URL也會被完整地保留下來。
相比之下,POST請求通過HTTP消息主體傳遞參數,并不直接暴露給用戶或顯示在地址欄上。因此,在用戶查看瀏覽器歷史記錄時,并沒有POST請求所攜帶的具體參數信息可見。
6.參數大小不同:GET請求在URL中傳送的參數是有長度限制的,而POST沒有。
GET請求本身是沒有長度限制的,但是URL有。不同的瀏覽器對于GET的長度限制也不一樣。
IE:對IE瀏覽器URL的最大長度為2083個字符。Firefox:對Firefox瀏覽器URL的最大長度為65536個字符。 Safari: 對Safari瀏覽器URL的最大長度為80000個字符。 Opera: 對Opera瀏覽器URL的最大長度為190000個字符。Google(chrome):對Google瀏覽器URL的最大長度為8182個字符。
所以,在需要兼容IE的情況下,URL請求的長度最長只能有2083個字符。
7.參數的數據類型不同:對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
GET方法通常用于從服務器獲取數據,并且將參數附加到URL的查詢字符串中。由于URL是以ASCII字符編碼表示的,因此GET請求只接受ASCII字符作為參數值。
例如,在下面的URL中:
http://example.com/search?keyword=hello&category=1
keyword
和 category
是兩個參數名,而 hello 和 1 是它們對應的值。這些值需要進行URL編碼,以確保它們只包含有效的ASCII
字符,并且不會破壞URL結構。
而POST方法與GET不同,POST請求將參數放置在HTTP請求正文(body)
中發送給服務器。正文可以包含任何類型的數據,并沒有限制為ASCII字符。
通過POST方法發送數據時,通常使用表單(form)來組織數據并將其封裝在表單字段(field)中。
例如,在HTML登錄表單中:
<form action="http://example.com/submit" method="post"><input type="text" name="username" value="John Doe"><input type="password" name="password"><input type="submit" value="Submit">
</form>
當用戶填寫用戶名和密碼后點擊提交按鈕時,瀏覽器會向服務器發送一個POST請求,并將用戶名和密碼作為非限制性ASCII字符一起發送到服務器。
所以GET方法只接受ASCII
字符作為參數值,并將參數附加到URL的查詢字符串中。而POST方法沒有限制數據類型,并且通過HTTP請求正文發送數據給服務器。
8.安全性不同:GET參數通過URL傳遞,POST放在Request body中,GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。
我們在使用GET請求時,參數會直接附加在URL后面,在瀏覽器地址欄中可見。
而使用POST請求時,參數通過HTTP消息體進行傳輸,并不會直接顯示在URL上。
所以可以說,在網絡環境下(如公共Wi-Fi),GET請求可能更容易遭受惡意截獲或攔截。
并且GET請求將參數作為查詢字符串明文展示在URL中,這些URL很容易被緩存、保存到歷史記錄或者日志文件中。
如果包含敏感信息的URL被泄露、共享或者留存在公開場合,則可能帶來安全隱患。
但是這些缺陷與不同其實都不是它們天生就是如此的,而是后天人為造成的。為什么這么說呢?接下來聽讓我扒開GET和POST的外衣,讓你好好看清楚就知道了。
首先我們要知道GET和POST是什么?
GET和POST是HTTP請求的兩種方法
那HTTP又是什么?
HTTP是基于TCP/IP的關于數據應該如何在互聯網中傳輸的協議。
既然HTTP的底層是TCP和IP。那么我們的GET和POST的底層也應該是TCP和IP,也就是說,GET請求和POST請求底層都是通過TCP鏈接的。GET和POST的功能是一樣的。如果我們要給GET加上request body,給POST帶上url參數,技術上是完全行的通的。
既然如此,那么我們上面所說的那些區別又是怎么回事呢?你是否也很矛盾?
其實很好理解
在我們廣闊的互聯網世界中,TCP就像是汽車一樣。我們使用TCP來傳輸數據,它非常可靠,從不會發生丟失或損壞的情況。
但是如果所有行駛在路上的汽車看起來都完全相同,那這個世界將變得一片混亂。
例如,急需送貨物的汽車可能會被前面滿載貨物的汽車攔截在路上,整個交通系統可能會癱瘓。為了避免這種情況發生,在這個互聯網世界中誕生了一個叫做HTTP的交通規則。
HTTP給予汽車運輸設定了多種服務類別,其中包括GET、POST、PUT和DELETE等方法。
根據HTTP規則,在執行GET請求時,需要給汽車貼上GET標簽(設置method為GET),并要求將要傳遞的數據放置在車頂位置(URL中)以便記錄和查找。而對于POST請求,則需要貼上POST標簽,并將貨物放置在車廂內部。
當然,在執行GET請求時也可以偷偷地把一些貨物藏進車廂里面去,但這顯然是不道德的行為;同樣地,在執行POST請求時也可以把一些數據放置到URL中去讓人感覺有點愚蠢。
值得注意的是,HTTP僅僅是一套行為準則,而TCP才是實際上實現GET和POST等方法的基礎。
所以,這些缺陷與不同其實都不是它們天生就是如此的,而是后天人為規定造成的。所以當面試官問我們get和post有什么不同時我們應該回答上面所說的8種不同,但是我們腦子里要清晰的知道它們其實是一樣的,只是后天的人為規定造成了它們之間的不同和缺陷