在面試或者筆試時,常常會被問到 HTTP 方法中 get 和 post 的異同點。本文簡單整理概括了一下,以備忘。css
一些 web 相關職位的面試,不管有沒有提 web,面試中的 get/post,通常就是指 web 中的 get/post。須要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集,因此若是談 get 與 post 的區別,要是面試官有心挖坑,就要特別注意下大家聊的是否是 web 中的 get/post。(本文接下去講的 get/post 基本上是基於 web 的)html
關於 get/post,能夠查看 rfc-2616 瞭解詳情:web
其實,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 的話顧名思義就是發送數據,因此須要帶上數據。ajax
何謂安全?這裏的安全指的是在規範的定義下,get 操做不會修改服務器的數據,不管作多少次 get 請求,服務端的數據都是不會有變化的,因此說 get 請求是安全的。"get 請求是安全的" 換句話說就是 "get 請求不產生反作用",它僅僅是獲取資源信息,就像數據庫查詢同樣,不會修改,增長數據,不會影響資源的狀態。chrome
何謂冪等?冪等是說,同一個請求原封不動的發送 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。緩存
這裏的 "安全",和第二點所講的 "安全" 又是兩回事了。這裏的 "安全" 是密碼學上的,也就是大多數場景中 "安全" 的意思。安全
其實該點很有點(post)五十步笑(get)百步之嫌。
咱們知道,get 請求是將數據附在 url 上,而 post 是將數據封裝在 request body 中。因此 get 請求附加的參數可能會被人在瀏覽器地址欄上直接看到,或者查看一下瀏覽器的歷史記錄或者日誌,就能看到你的參數。而 post 由於不能被緩存,也不能被保存爲書籤,因此請求過了就沒有記錄了?請求參數就不能被截獲了?非也,抓個包就能夠看到了。
因此,post 請求只是相對安全的。(防君子防不了小人)
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 數據是沒有限制的,起限制做用的是服務器的處理程序的處理能力。
這點很是容易理解,打開一個頁面,若是以前打開過,那麼很明顯速度會加快,這是由於 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,須要清除該地址的緩存!
因此通常要獲取最新的文件(非緩存文件),能夠加個相似時間戳同樣的參數。
form 表單有個 method 屬性,通常爲 "post"。可是,其實 method 屬性是能夠爲 "get" 的,甚至,默認就是 "get"。
若是是 "post" 方式,數據藏在 request body 中,若是是 "get" 方式,數據拼接在 url 上。可是,通常 form 表示都與 "數據提交" 相輔相成,會對服務端數據作修改,因此通常都是以 "post" 的方式。
說完 get/post,再來簡單談談他們的其餘幾個好基友吧。
Http 定義了與服務器交互的不一樣方法,最基本的方法有 4 種,分別是 GET,POST,PUT,DELETE。URL 全稱是資源描述符,咱們能夠這樣認爲:一個 URL 地址,它用於描述一個網絡上的資源,而 HTTP 中的 GET,POST,PUT,DELETE 就對應着對這個資源的查,改,增,刪 4 個操做。
get 和 post 成功以後應該返回 200;而 put 和 delete 在成功時則推薦使用 202.