get與post需要注意的幾點


在面試或者筆試時,經常會被問到 HTTP 方法中 get 和 post 的異同點。本文簡單整理歸納了一下,以備忘。

1、"get/post" VS "web 中的 get/post"

一些 web 相關職位的面試,無論有沒有提 web,面試中的 get/post,一般就是指 web 中的 get/post。需要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集,所以如果談 get 與 post 的區別,要是面試官有心挖坑,就要特別注意下你們聊的是不是 web 中的 get/post。(本文接下去講的 get/post 基本上是基於 web 的)

關於 get/post,可以查看 rfc-2616 了解詳情:

其實,http 中的 get 與 post 只是單純的名字上的區別,get 請求的數據也可以放在 request body 中,只是瀏覽器沒有實現它,但是 get 並不只是在 web 中使用。所以,說到 get/post 的區別,會直接條件反射地去說 web 中的 get/post 區別。而 web 中 get 以及 post,其實都可以往服務端發送數據,get 是將數據拼接在 url 上(有必要時需要 encode),而 post 是將數據封裝在 request body 中,發送過去。

get/post 可以顧名思義地理解,get 是用來請求數據,那么,既然是請求數據,為什么還要帶上數據呢?其實很好理解,比如一個新聞頁面,有很多內頁,那么 get 請求可能帶上的類似這樣的參數 page=1,即為請求第一頁的數據。post 的話顧名思義就是發送數據,所以需要帶上數據。

2、get 請求是安全和冪等的

何謂安全?這里的安全指的是在規范的定義下,get 操作不會修改服務器的數據,無論做多少次 get 請求,服務端的數據都是不會有變化的,所以說 get 請求是安全的。"get 請求是安全的" 換句話說就是 "get 請求不產生副作用",它僅僅是獲取資源信息,就像數據庫查詢一樣,不會修改,增加數據,不會影響資源的狀態。

何謂冪等?冪等是說,同一個請求原封不動的發送 N 次和 M 次(N 不等於 M,N 和 M 都大於 1),服務器上資源的狀態最終是一致的,相應地服務器返回的內容也是一致的。get 請求是冪等的,因為無論請求多少次,服務器上的資源狀態不變,而 post 則不然,post 會更新服務器的數據。比如發貼是非冪等的,重復 10 次發貼請求會創建 10 個帖子。但修改帖子內容是冪等的,一個修改請求重復無論多少次,帖子最終狀態都是一致的。

關於冪等再舉個數學上的例子。對於單目運算,如果一個運算對於在范圍內的所有的一個數多次進行該運算所得的結果和進行一次該運算所得的結果是一樣的,那么我們就稱該運算是冪等的。比如絕對值運算就是一個例子,在實數集中,有 abs(a)=abs(abs(a))。這個例子非常的好,abs(a) 可以表示做了一次 get 請求后的服務器上的資源狀態,對其繼續做 abs 運算,狀態不變,這就好比做了一次 get 請求,繼續再做,而該資源狀態一直不變,所以請求得到的東西也就不會變。

因此,按照某一 ID 閱覽文章就是安全而冪等的,應當使用 get。而注冊用戶、登錄等操作會改變服務器的資源狀態,不是安全而冪等的,應當使用 post。

3、post 相對 get 請求是 "安全" 的

這里的 "安全",和第二點所講的 "安全" 又是兩回事了。這里的 "安全" 是密碼學上的,也就是大多數場景中 "安全" 的意思。

其實該點頗有點(post)五十步笑(get)百步之嫌。

我們知道,get 請求是將數據附在 url 上,而 post 是將數據封裝在 request body 中。所以 get 請求附加的參數可能會被人在瀏覽器地址欄上直接看到,或者查看一下瀏覽器的歷史記錄或者日志,就能看到你的參數。而 post 因為不能被緩存,也不能被保存為書簽,所以請求過了就沒有記錄了?請求參數就不能被截獲了?非也,抓個包就可以看到了。

所以,post 請求只是相對安全的。(防君子防不了小人)

4、get 請求發送數據更小

http 協議中的 get/post 並沒有發送數據大小的限制,對發送數據大小產生限制的是瀏覽器以及操作系統、服務器,http 本身並沒有對 url 長度有所限制

IE 對 URL 長度的限制是 2083字節(<=IE 8)。對於其他瀏覽器,如 Netscape、FireFox 等,理論上沒有長度限制,其限制取決於操作系統以及服務器的支持。而 chrome 遇到長度很長的 URL 時,會直接 崩潰

URL 長了,對服務器處理也是一種負擔。原本一個會話就沒有多少數據,現在如果有人惡意地構造幾個幾 M 大小的 URL,並不停地訪問你的服務器。服務器的最大並發數顯然會下降。另一種攻擊方式是,把告訴服務器 Content-Length 是一個很大的數,然后只給服務器發一點兒數據,嘿嘿,服務器你就傻等着去吧。哪怕你有超時設置,這種故意的次次訪問超時也能讓服務器吃不了兜着走。有鑒於此,多數服務器出於安全啦、穩定啦方面的考慮,會給 URL 長度加限制。

理論上講,POST 是沒有大小限制的,HTTP 協議規范也沒有進行大小限制,說 "POST數據量存在80K/100K 的大小限制" 是不准確的,POST 數據是沒有限制的,起限制作用的是服務器的處理程序的處理能力。

5、get 能被緩存,post 不能被緩存

這點非常容易理解,打開一個頁面,如果之前打開過,那么很明顯速度會加快,這是因為 html/js/css/img 等文件都能被瀏覽器緩存(也可以被服務器緩存),而這些文件的獲取,都是用的 get 請求。事實上,web 中的絕大多數請求都是用 get 完成的,post 請求目前為止我只是在 ajax 以及 form 表單中有見過。

但是實際上,http 協議中 post 和 get 都是可以被緩存的,不過不要驚訝,瀏覽器的實現總是比標准厲害。(post 和 get 真的只有名字上的區別啊。。)

因為 get 請求會有緩存,所以在開發過程中,很多時候我們要手動清除緩存,不然看不到修改后的樣子。

關於 get 請求能被緩存我有個慘痛的經歷。在一次開發中,要做一個跳轉頁面(假設為 a.index,同時需要在主頁面(假設為 index.htm)中帶個參數(假設為 tmp)過去,為了方便,直接將參數附加在了跳轉頁面的 url 上,頁面地址為 a.htm?tmp,直接取其 location.search 屬性即可獲取參數。之后修改了 a.htm 頁面的內容,但是發現一直不生效,並且已經清除了 a.htm 頁面的緩存,排查了很久,原因很顯然,緩存地址為 a.htm?tmp,需要清除該地址的緩存!

所以一般要獲取最新的文件(非緩存文件),可以加個類似時間戳一樣的參數。

6、form 表單可以用 get 提交

form 表單有個 method 屬性,一般為 "post"。但是,其實 method 屬性是可以為 "get" 的,甚至,默認就是 "get"。

如果是 "post" 方式,數據藏在 request body 中,如果是 "get" 方式,數據拼接在 url 上。但是,一般 form 表示都與 "數據提交" 相輔相成,會對服務端數據做修改,所以一般都是以 "post" 的方式。

7、求他:put 以及 delete

說完 get/post,再來簡單談談他們的其他幾個好基友吧。

Http 定義了與服務器交互的不同方法,最基本的方法有 4 種,分別是 GET,POST,PUT,DELETE。URL 全稱是資源描述符,我們可以這樣認為:一個 URL 地址,它用於描述一個網絡上的資源,而 HTTP 中的 GET,POST,PUT,DELETE 就對應着對這個資源的查,改,增,刪 4 個操作。

  • GET:無副作用,冪等,不可帶 Request Body
  • PUT:副作用,冪等,可以帶 Request Body
  • POST:副作用,非冪等,可以帶 Request Body
  • DELETE:副作用,冪等,不可帶 Request Body

get 和 post 成功之后應該返回 200;而 put 和 delete 在成功時則推薦使用 202.

8、Read More


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM