拋磚引玉,聊下概念性的東西先:
HTTP協議 (Hyper Text Transfer Protocol)
HTTP是一個基於TCP/IP通信協議來傳遞數據,包括html文件、圖像、結果等,即是一個客戶端和服務器端請求和應答的標准。
HTTP協議特點
1.http無連接:限制每次連接只處理一個請求,服務端完成客戶端的請求后,即斷開連接。(傳輸速度快,減少不必要的連接,但也意味着每一次訪問都要建立一次連接,效率降低)
2.http無狀態:對於事務處理沒有記憶能力。每一次請求都是獨立的,不記錄客戶端任何行為。(優點解放服務器,但可能每次請求會傳輸大量重復的內容信息)
3.客戶端/服務端模型:客戶端支持web瀏覽器或其他任何客戶端,服務器通常是apache或者iis等
4.簡單快速
5.靈活:可以傳輸任何類型的數據
客戶端請求消息
客戶端發送一個請求到服務器的請求消息包括以下格式:
請求行,請求頭部,空行,請求數據 (圖片來自網絡)
服務器響應消息
服務器響應包括如下格式:
狀態行,消息報頭,空行,響應正文
序號 | 方法 | 描述 |
1 | GET | 發送請求來獲得服務器上的資源,請求體中不會包含請求數據,請求數據放在協議頭中。另外get支持快取、緩存 、可保留書簽等。冪等 |
2 | POST | 和get一樣很常見,向服務器提交資源讓服務器處理,比如提交表單、上傳文件等,可能導致建立新的資源或者對 原有資源的修改。提交的資源放在請求體中。不支持快取。非冪等 |
3 | HEAD | 本質和get一樣,但是響應中沒有呈現數據,而是http的頭信息,主要用來檢查資源或超鏈接的有效性或是否可以可達、檢 查網頁是否被串改或更新,獲取頭信息等,特別適用在有限的速度和帶寬下。 |
4 | PUT | 和post類似,html表單不支持,發送資源與服務器,並存儲在服務器指定位置,要求客戶端事先知 道該位置;比如post是在一個集合上(/province),而put是具體某一個資源上(/province/123)。所以put是安全的, 無論請求多少次,都是在123上更改,而post可能請求幾次創建了幾次資源。冪等 |
5 | DELETE | 請求服務器刪除某資源。和put都具有破壞性,可能被防火牆攔截。如果是https協議,則無需擔心。冪等 |
6 | CONNECT | HTTP/1.1協議中預留給能夠將連接改為管道方式的代理服務器。就是把服務器作為跳板,去訪問其他網頁 然后把數據返回回來,連接成功后,就可以正常的get、post了。 |
7 | OPTIONS | 獲取http服務器支持的http請求方法,允許客戶端查看服務器的性能,比如ajax跨域時的預檢等。 |
8 | TRACE | 回顯服務器收到的請求,主要用於測試或診斷。一般禁用,防止被惡意攻擊或盜取信息。 |
GET 和 POST 比較
GET | POST | |
點擊返回/刷新按鈕 | 沒有影響 | 數據會重新提交 |
緩存/添加書簽 | 可以 | 不可以 |
歷史記錄 | 有 | 沒有 |
編碼類型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。為二進制數據使用 多重編碼 |
是否冪等 | 冪等 | 非冪等 |
長度限制 | http協議沒有限制,但是實際瀏覽器或服務 器有(最大2048) |
理論上沒有,可能會收到服務器配置或內存限制 |
數據類型限制 | 只能ASCII,非ascii都要編碼傳輸 | 沒有限制,允許二進制數據 |
安全性 | 數據全部展示在url中,不安全 | 相比get,通過request body傳遞數據,比較安全 |
可見效 | 可見 | 不可見 |
注意:以上只是一種規范,如果非要給get加上request body,或者給post的url上帶上參數,技術上沒有任何問題。
另外曾經看到一篇文章聽說『99% 的人都理解錯了 HTTP 中 GET 與 POST 的區別』??說,get發送1個tcp包,而post發送兩個tcp包,后來被驗證這個說法是不正確的,其實get如果也發送body,則也會發送Expect:100
PATCH 和 PUT 比較
PATCH | PUT | |
是否冪等 | 非冪等 | 冪等 |
粒度 | 局部,最小粒度,節約網絡帶寬 | 所有 |
注意:比如更新一個userinfo,包含name,age,sex等多個字段,如果只修改了age,如果用put來更新,則需要把其他沒有變更的也要提交到服務器,但是使用patch,則只需要提交age到服務器即可。這都是協議層面來討論的。
GET
請求示例
GET https://testrail-tools.trendmicro.com/portal/admin/getTimerInitStatus HTTP/1.1 Accept: application/json, text/javascript, */*; q=0.01 X-Requested-With: XMLHttpRequest Referer: https://testrail-tools.trendmicro.com/portal/admin/toLicenseTimerConfig?id=7 Accept-Language: zh-CN Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko Host: testrail-tools.trendmicro.com Connection: Keep-Alive Cookie: _ga=GA1.2.1909963682.1524537669; _gid=GA1.2.563928490.1529501401
以上對應
第1行 請求行
請求方法(get)+空格+url(https://testrail-tools.trendmicro.com/portal/admin/getTimerInitStatus)+空格+協議版本(HTTP/1.1)
第2-10都是請求頭部
Accept:表示客戶端接受的內容類型,按照先后順序表示客戶端接收數據的先后次序
X-Requested-With:以x開頭的是非http標准,一般是某種技術的出現而定義的;這里是用來判斷是http請求還是ajax請求。
Referer:從這個頁面訪問請求行里的url
Accept-Language:客戶端接受內容返回優先選擇的語言
Accept-Encoding:客戶端可以接受的服務器對返回內容進行編碼壓縮的格式。
User-Agent:客戶端運行的瀏覽器類型信息。
Host:頭域指定請求的服務器的地址和端口,HTTP/1.1必須包括Host,否則返回400
Connection:表示是否需要持久連接。如果web服務器端看到這里的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久連接),它就可以利用持久連接的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點, web服務器需要在返回給客戶端HTTP頭信息中發送一個Content-Length(返回信息正文的長度)頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,然 后在正式寫出內容之前計算它的大小。
Cookie:http請求時,會把保存的cookie也發送服務器。cookie是保存在客戶端里的,分為內存cookie和硬盤cookie。前者隨着瀏覽器關閉而消失,后者由過期時間或者用戶手動清除。因為http請求是無狀態的,所以服務器為了認證,會生成sessionid,讓瀏覽器setcookie保存起來,每次請求攜帶上認證信息。這部份以后再聊吧。
響應示例
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Cache-Control: private Expires: Wed, 31 Dec 1969 16:00:00 PST X-Application-Context: application:prod Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 20 Jun 2018 15:00:16 GMT {"advancewarn":"1","userstatus":"1","ldap":"1","licensealarm":"1","deltempzipfile":"1","sctmlicense":"0","user":"1"}
第1行 狀態行
第2-8 消息報頭
Server:包含處理請求的服務器信息,包含多個產品注釋和標識。
Cache-Control:告知緩存機制是否可以緩存和類型,private是只能當前用戶,不能被共享。
Expires:響應過期時間
X-Application-Context:application配置,這里表示讀取的是application-prod.properties
Content-Type:返回數據的類型和字符編碼格式
Transfer-Encoding:告知接收端,報文采取了何種編碼,chunked表示服務器無法確定消息大小,一般比如下載等,就采用chunked。
Date:返回消息的時間
第 9 行 空行
第 10 行 響應正文
消息報頭指定了是返回json字符串。
POST
請求示例
POST https://testrail-tools.trendmicro.com/portal/admin/editTimer HTTP/1.1 Host: testrail-tools.trendmicro.com Connection: keep-alive Content-Length: 35 Accept: application/json, text/javascript, */*; q=0.01 Origin: https://testrail-tools.trendmicro.com X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Referer: https://testrail-tools.trendmicro.com/portal/admin/toAdminTimerConfig?id=7 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: _ga=GA1.2.199305797.1501211992; _ga=GA1.1.199305797.1501211992; _gid=GA1.2.56449187.1529562439; _gat_gtag_UA_111346521_2=1 type=del&interval=1200&timelag=7200
第1行同 get
第2-13 行 請求頭部
Content-Length:告知服務器,請求數據的大小
Origin:origin類似refered,但比refered更人性化,origin只出現在post中,而origin也不攜帶敏感信息和具體url路徑。
Content-Type:http請求提交內容的編碼類型,一般只有post需要設置。application/x-www-form-urlencoded(缺省)和multipart/form-data。
第14行 空行
第15行 請求數據
響應示例
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Application-Context: application:prod Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Thu, 21 Jun 2018 07:36:58 GMT {"result":"edit timer success"}
其他這里就不累述了。
說了這么多,這么多請求方式都是http協議的標准,你完全可以隨心所欲,全部用post或者全部用get,但是你要是開發的是商業產品,那你就要為你自己的隨便買單咯。
好比刪除一樣東西,如果用get請求方式:http:/xxx/delete?id=1,那你很快就知道,這些標准也能讓其他人一眼就能知道具體所要做的意思。
HTTP狀態碼
摘自HTTP狀態碼
分類 | 分類描述 |
---|---|
1** | 信息,服務器收到請求,需要請求者繼續執行操作 |
2** | 成功,操作被成功接收並處理 |
3** | 重定向,需要進一步的操作以完成請求 |
4** | 客戶端錯誤,請求包含語法錯誤或無法完成請求 |
5** | 服務器錯誤,服務器在處理請求的過程中發生了錯誤 |
狀態碼 | 狀態碼英文名稱 | 中文描述 |
---|---|---|
100 | Continue | 繼續。客戶端應繼續其請求 |
101 | Switching Protocols | 切換協議。服務器根據客戶端的請求切換協議。只能切換到 更高級的協議,例如,切換到HTTP的新版本協議 |
200 | OK | 請求成功。一般用於GET與POST請求 |
201 | Created | 已創建。成功請求並創建了新的資源 |
202 | Accepted | 已接受。已經接受請求,但未處理完成 |
203 | Non-Authoritative Information | 非授權信息。請求成功。但返回的meta信息不在原始的服務器 ,而是一個副本 |
204 | No Content | 無內容。服務器成功處理,但未返回內容。在未更新網頁 的情況下,可確保瀏覽器繼續顯示當前文檔 |
205 | Reset Content | 重置內容。服務器處理成功,用戶終端(例如:瀏覽器)應重 置文檔視圖。可通過此返回碼清除瀏覽器的表單域 |
206 | Partial Content | 部分內容。服務器成功處理了部分GET請求 |
300 | Multiple Choices | 多種選擇。請求的資源可包括多個位置,相應可返回一個 資源特征與地址的列表用於用戶終端(例如:瀏覽器)選擇 |
301 | Moved Permanently | 永久移動。請求的資源已被永久的移動到新URI,返回信息 會包括新的URI,瀏覽器會自動定向到新URI。今后任何新的請求 都應使用新的URI代替 |
302 | Found | 臨時移動。與301類似。但資源只是臨時被移動。客戶端應繼 使用原有URI |
303 | See Other | 查看其它地址。與301類似。使用GET和POST請求查看 |
304 | Not Modified | 未修改。所請求的資源未修改,服務器返回此狀態碼時,不會 返回任何源。客戶端通常會緩存訪問過的資源,通過提供一個頭 信息指出客戶端希望只返回在指定日期之后修改的資源 |
305 | Use Proxy | 使用代理。所請求的資源必須通過代理訪問 |
306 | Unused | 已經被廢棄的HTTP狀態碼 |
307 | Temporary Redirect | 臨時重定向。與302類似。使用GET請求重定向 |
400 | Bad Request | 客戶端請求的語法錯誤,服務器無法理解 |
401 | Unauthorized | 請求要求用戶的身份認證 |
402 | Payment Required | 保留,將來使用 |
403 | Forbidden | 服務器理解請求客戶端的請求,但是拒絕執行此請求 |
404 | Not Found | 服務器無法根據客戶端的請求找到資源(網頁)。通過此代 碼,網站設計人員可設置"您所請求的資源無法找到"的個性 頁面 |
405 | Method Not Allowed | 客戶端請求中的方法被禁止 |
406 | Not Acceptable | 服務器無法根據客戶端請求的內容特性完成請求 |
407 | Proxy Authentication Required | 請求要求代理的身份認證,與401類似,但請求者應當使用代 理進行授權 |
408 | Request Time-out | 服務器等待客戶端發送的請求時間過長,超時 |
409 | Conflict | 服務器完成客戶端的PUT請求是可能返回此代碼,服務器處理 請求時發生了沖突 |
410 | Gone | 客戶端請求的資源已經不存在。410不同於404,如果資源以前有 現在被永久刪除了可使用410代碼,網站設計人員可通過301代碼 指定資源的新位置 |
411 | Length Required | 服務器無法處理客戶端發送的不帶Content-Length的請求信息 |
412 | Precondition Failed | 客戶端請求信息的先決條件錯誤 |
413 | Request Entity Too Large | 由於請求的實體過大,服務器無法處理,因此拒絕請求。為防 止客戶端的連續請求,服務器可能會關閉連接。如果只 是服務器暫時無法處理,則會包含一個Retry-After的響應信息 |
414 | Request-URI Too Large | 請求的URI過長(URI通常為網址),服務器無法處理 |
415 | Unsupported Media Type | 服務器無法處理請求附帶的媒體格式 |
416 | Requested range not satisfiable | 客戶端請求的范圍無效 |
417 | Expectation Failed | 服務器無法滿足Expect的請求頭信息 |
500 | Internal Server Error | 服務器內部錯誤,無法完成請求 |
501 | Not Implemented | 服務器不支持請求的功能,無法完成請求 |
502 | Bad Gateway | 充當網關或代理的服務器,從遠端服務器接收到了一個無效的請求 |
503 | Service Unavailable | 由於超載或系統維護,服務器暫時的無法處理客戶端的請求 。延時的長度可包含在服務器的Retry-After頭信息中 |
504 | Gateway Time-out | 充當網關或代理的服務器,未及時從遠端服務器獲取請求 |
505 | HTTP Version not supported | 服務器不支持請求的HTTP協議的版本,無法完成處理 |
結束語:其實我們大部分情況下只用到了GET和POST。如果想設計一個符合RESTful規范的web應用程序,則這六種方法都會用到。不過即使暫時不想涉及REST,
了解這六種方法的本質仍然是很有作用的。大家將會發現,原來web也是很簡潔明了的。下面再次依次說明這六種方法。