淺談Http的請求方式

看了網上很多的關於Http請求方式的文章,衆說紛紜,於是決定自己花點時間總結一番,與大家分享,如有不妥之處還望海涵。

Http的幾種請求方式:

HTTP是一個客戶端(用戶)和服務端(網站)之間請求和應答的標準。標準的存在意義就是爲了統一概念,只是HTTP協議的一種規範,也可以說是一種約定,語義化的定義可以使大家規範的獲取Http 請示方式後進行相應的資源處理。

GET

get請求是用來獲取數據的,只是用來查詢數據,不對服務器的數據做任何的修改,新增,刪除等操作。

在這裏我們認爲get請求是安全的,以及冪等的。安全就是指不影響服務器的數據,冪等是指同一個請求發送多次返回的結果應該相同。

特點:

get請求會把請求的參數附加在URL後面,這樣會產生安全問題(注入攻擊),如果是系統的登陸接口採用的get請求,需要對請求的參數做一個加密。

get請求其實本身HTTP協議並沒有限制它的URL大小,但是不同的瀏覽器對其有不同的大小長度限制

POST

向指定資源提交數據,請求服務器進行處理(例如提交表單或者上傳文件)。數據被包含在請求本文中。這個請求可能會創建新的資源或修改現有資源,或二者皆有。

PUT

client對一個URI發送一個Entity,服務器在這個URI下如果已經又了一個Entity,那麼此刻服務器應該替換成client重新提交的,也由此保證了PUT的冪等性。如果服務器之前沒有Entity ,那麼服務器就應該將client提交的放在這個URI上。總結一個字:PUT。對的,PUT的方法就是其字面表意,將client的資源放在請求URI上。對於服務器到底是創建還是更新,由服務器返回的HTTP Code來區別。

注:通過上面可以知道,如果用PUT來達到更改資源,需要client提交資源全部信息,如果只有部分信息,不應該使用PUT(因爲服務器使用client提交的對象整體替換服務器的資源)。

DELETE

請求服務器刪除Request-URI所標識的資源。

PATCH

PATCH 用於資源的部分內容的更新,例如更新某一個字段。具體比如說只更新用戶信息的電話號碼字段

而 PUT 用於更新某個資源較完整的內容,比如說用戶要重填完整表單更新所有信息,後臺處理更新時可能只是保留內部記錄 ID 不變。

HEAD

HEAD方法跟GET方法相同,只不過服務器響應時不會返回消息體。一個HEAD請求的響應中,HTTP頭中包含的元信息應該和一個GET請求的響應消息相同。這種方法可以用來獲取請求中隱含的元信息,而不用傳輸實體本身。也經常用來測試超鏈接的有效性、可用性和最近的修改。

簡而言之:

HEAD請求常常被忽略,但是能提供很多有用的信息,特別是在有限的速度和帶寬下。主要有以下特點:

1、只請求資源的首部;

2、檢查超鏈接的有效性;

3、檢查網頁是否被修改;

TRACE

回顯服務器收到的請求,主要用於測試或診斷。

OPTIONS

這個方法可使服務器傳回該資源所支持的所有HTTP請求方法。用’*'來代替資源名稱,向Web服務器發送OPTIONS請求,可以測試服務器功能是否正常運作

CONNECT

HTTP/1.1協議中預留給能夠將連接改爲管道方式的代理服務器。通常用於SSL加密服務器的鏈接(經由非加密的HTTP代理服務器)。
方法名稱是區分大小寫的。當某個請求所針對的資源不支持對應的請求方法的時候,服務器應當返回狀態碼405(Method Not Allowed),當服務器不認識或者不支持對應的請求方法的時候,應當返回狀態碼501(Not Implemented)。

GET 和 POST 請求的優缺點、區別以及誤區:

Get和Post在面試中一般都會問到,一般的區別:
(1)post更安全(不會作爲url的一部分,不會被緩存、保存在服務器日誌、以及瀏覽器瀏覽記錄中)
(2)post發送的數據更大(get有url長度限制)
(3)post能發送更多的數據類型(get只能發送ASCII字符)
(4)post比get慢
(5)post用於修改和寫入數據,get一般用於搜索排序和篩選之類的操作(淘寶,支付寶的搜索查詢都是get提交),目的是資源的獲取,讀取數據
雖然在開發中經常用get或者post請求,但是由於我們資歷經驗的欠缺,或許就重來沒有深究過什麼場合用get請求,什麼場合用post請求,我相信不止我一個人當看到第4,5條的時候,就會明白爲什麼面試官對我們的回答不滿意,也明白了自己對get或post用法理解的欠缺,那麼get比post更快,究竟快多少呢?表現在那些方面?

一、爲什麼get比post更快
1.post請求包含更多的請求頭
因爲post需要在請求的body部分包含數據,所以會多了幾個數據描述部分的首部字段(如:content-type),這其實是微乎其微的。

2.最重要的一條,post在真正接收數據之前會先將請求頭髮送給服務器進行確認,然後才真正發送數據
post請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回100 Continue響應
(5)瀏覽器發送數據
(6)服務器返回200 OK響應
get請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回200 OK響應
也就是說,目測get的總耗是post的2/3左右,這個口說無憑,網上已經有網友進行過測試。

3.get會將數據緩存起來,而post不會
可以做個簡短的測試,使用ajax採用get方式請求靜態數據(比如html頁面,圖片)的時候,如果兩次傳輸的數據相同,第二次以後消耗的時間將會在10ms以內(chrome測試),而post每次消耗的時間都差不多。經測試,chrome和firefox下如果檢測到get請求的是靜態資源,則會緩存,如果是數據,則不會緩存,但是IE什麼都會緩存起來,當然,應該沒有人用post去獲取靜態數據吧,反正我是沒見過。

4.post不能進行管道化傳輸
http權威指南中是這樣說的:http的一次會話需要先建立tcp連接(大部分是tcp,但是其他安全協議也是可以的),然後才能通信,如果 每次連接都只進行一次http會話,那這個連接過程佔的比例太大了!於是出現了持久連接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,當然兩者不僅僅是命名上的差別,http/1.1中,持久連接是默認的,除非顯示在connection中添加close,否則持久連接不會關閉,而http/1.0+中則恰好相反,除非顯示在connection首部中添加keep-alive,否則在接收數據包後連接就斷開了。
出現了持久連接還不夠,在http/1.1中,還有一種稱爲管道通信的方式進行速度優化:把需要發送到服務器上的所有請求放到輸出隊列中,在第一個請求發送出去後,不等到收到服務器的應答,第二個請求緊接着就發送出去,但是這樣的方式有一個問題:不安全,如果一個管道中有10個連接,在發送出9個後,突然服務器告訴你,連接關閉了,此時客戶端即使收到了前9個請求的答覆,也會將這9個請求的內容清空,也就是說,白忙活了……此時,客戶端的這9個請求需要重新發送。這對於冪等請求還好(比如get,多發送幾次都沒關係,每次都是相同的結果),如果是post這樣的非冪等請求(比如支付的時候,多發送幾次就慘了),肯定是行不通的。
所以,post請求不能通過管道的方式進行通信!很有可能,post請求需要重新建立連接,這個過程不跟完全沒優化的時候一樣了麼?所以,在可以使用get請求通信的時候,不要使用post請求,這樣用戶體驗會更好,當然,如果有安全性要求的話,post會更好。管道化傳輸在瀏覽器端的實現還需考證,貌似默認情況下大部分瀏覽器(除了opera)是不進行管道化傳輸的,除非手動開啓!

二、get傳參最大長度的理解誤區
1.總結
(1)http協議並未規定get和post的長度限制
(2)get的最大長度限制是因爲瀏覽器和web服務器限制了URL的長度
(3)不同的瀏覽器和web服務器,限制的最大長度不一樣
(4)要支持IE,則最大長度爲2083byte,若支持Chrome,則最大長度8182byte

2.誤解
(1)首先即使get有長度限制,也是限制的整個URL的長度,而不僅僅是參數值數據長度,http協議從未規定get/post的請求長度限制是多少
(2)所謂的請求長度限制是由瀏覽器和web服務器決定和設置的,各種瀏覽器和web服務器的設定均不一樣,這依賴於各個瀏覽器廠家的規定或者可以根據web服務器的處理能力來設定。IE 和 Safari 瀏覽器 限制 2k,Opera 限制4k,Firefox 限制 8k(非常老的版本 256byte),如果超出了最大長度,大部分的服務器直接截斷,也有一些服務器會報414錯誤。

總結

雖然上面定義了Http請求方式的使用方式,但實際開發中並不一定要完全按照上面的標準,這些指定的標準只是讓我們加以參考的技術規範。實際上請求方式的意義也在於真正的業務中體現。例如:get請求方式本要求只進行查詢,但實際也有些開發人員也用於了更新和刪除。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章