HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是基於客戶端/服務端(C/S)的架構模型,經過一個可靠的連接來交換信息,是一個無狀態、無鏈接、媒體獨立的請求/響應協議。用於從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議html
HTTP基於TCP/IP通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。git
HTTP協議工做於客戶端-服務端架構上。瀏覽器做爲HTTP客戶端經過URL向HTTP服務端即WEB服務器發送全部請求。github
Web服務器有:Apache服務器,IIS服務器(Internet Information Services)等。web
Web服務器根據接收到的請求後,向客戶端發送響應信息。ajax
HTTP默認端口號爲80,可是你也能夠改成8080或者其餘端口。算法
Request編程
請求行(request line)、請求頭部(header)、空行和請求數據四個部分組成,下圖給出了請求報文的通常格式。瀏覽器
Response緩存
響應也由四個部分組成,分別是:狀態行、消息報頭、空行和響應正文。安全
安全性,僅指該方法的***屢次調用不會產生反作用***,不涉及傳統意義上的「安全」,這裏的***反作用是指資源狀態***。即,安全的方法不會修改資源狀態,儘管屢次調用的返回值可能不同(被其餘非安全方法修改過)。
冪等性,是指該方法***屢次調用返回的效果(形式)一致***,客戶端能夠重複調用而且指望一樣的結果。冪等的含義相似於編程語言中的setter方法[1],一次調用和屢次調用產生的效果是一致的,都是對一個變量進行賦值。安全性和冪等性含義有些接近,容易搞混。
HTTP方法的安全性和冪等性見下表 :
方法名 | 安全性 | 冪等性 |
---|---|---|
GET | 是 | 是 |
HEAD | 是 | 是 |
OPTIONS | 是 | 是 |
DELETE | 否 | 是 |
PUT | 否 | 是 |
POST | 否 | 否 |
(1)能夠認爲安全的方法都是隻讀的方法(GET, HEAD, OPTIONS)
(2)DELETE方法的語義表示刪除服務器上的一個資源,第一次刪除成功後該資源就不存在了,資源狀態改變了,因此DELETE方法不具有安全特性。然而***HTTP協議規定DELETE方法是冪等的***,每次刪除該資源都要返回狀態碼200 OK,服務器端要實現冪等的DELETE方法,必須記錄全部已刪除資源的元數據(Metadata),不然,第二次刪除後返回的響應碼就會相似404 Not Found了。
(3)PUT和POST方法語義中都有修改資源狀態的意思,所以都不是安全的。可是PUT方法是冪等的,POST方法不是冪等的,這麼設計的理由是:
1xx 表示通知信息的,如請求收到了或正在進行處理,須要請求者繼續執行操做。
2xx 表示成功,如接受或知道了。
3xx 表示重定向,表示要完成請求還必須採起進一步的行動。
4xx 表示客戶的差錯,如請求中有錯誤的語法或不能完成。
5xx 表示服務器的差錯,如服務器失效沒法完成請求。
100 Continue
- HTTP
100 Continue
信息狀態響應代碼代表目前爲止的全部內容都是正常的,而且客戶端應該繼續請求或者若是它已經完成則忽略它。- 狀態:100 Continue
101 Switching Protocols
200 OK 服務器成功處理了請求
204 請求被受理但沒有資源能夠返回
206
HTTP
206 Partial Content
成功狀態響應代碼指示請求已成功而且主體包含所請求的數據範圍,如Range
請求標題中所述。若是隻有一個範圍,則整個響應Content-Type
設置爲文檔的類型,並提供一個Content-Range
。若是發送了幾個範圍,則Content-Type
設置爲multipart/byteranges
而且每一個片斷都覆蓋一個範圍,而且使用Content-Range
和Content-Type
對其進行描述。狀態 :206 Partial Content
實例:
包含一個範圍的響應: HTTP/1.1 206 Partial Content Date: Wed, 15 Nov 2015 06:25:24 GMT Last-Modified: Wed, 15 Nov 2015 04:58:08 GMT Content-Range: bytes 21010-47021/47022 Content-Length: 26012 Content-Type: image/gif ... 26012 bytes of partial image data ... 包含如下幾個範圍的響應: HTTP/1.1 206 Partial Content Date: Wed, 15 Nov 2015 06:25:24 GMT Last-Modified: Wed, 15 Nov 2015 04:58:08 GMT Content-Length: 1741 Content-Type: multipart/byteranges; boundary=String_separator --String_separator Content-Type: application/pdf Content-Range: bytes 234-639/8000 ...the first range... --String_separator Content-Type: application/pdf Content-Range: bytes 4590-7999/8000 ...the second range --String_separator-- 複製代碼
狀態: 206 Partial Content
301 永久性重定向,請求的URL已移走
- 被請求的資源已永久移動到新位置,而且未來任何對此資源的引用都應該使用本響應返回的若干個URI之一。若是可能,擁有連接編輯功能的客戶端應當自動把請求的地址修改成從服務器反饋回來的地址。除非額外指定,不然這個響應也是可緩存的。新的永久性的URI應當在響應的Location域中返回。除非這是一個HEAD請求,不然響應的實體中應當包含指向新的URI的超連接及簡短說明。
- 若是這不是一個GET或者HEAD請求,所以瀏覽器禁止自動進行重定向((第二次 POST 時,環境可能已經發生變化(POST 方法不是冪等))),除非獲得用戶的確認,由於請求的條件可能所以發生變化。
- 注意:對於某些使用HTTP/1.0協議的瀏覽器,當它們發送的POST請求獲得了一個301響應的話,接下來的重定向請求將會變成GET方式。
- 搜索引擎更新它們到資源的連接(在 SEO 中,聽說連接汁被髮送到新的 URL)
- 狀態: 301 Moved Permanently
res.writeHead(301,{ 'Location': 'http://127.0.0.1:3000/login' }) 複製代碼
302 臨時重定向,維護
- 要求客戶端執行臨時重定向(原始描述短語爲「Moved Temporarily」)。因爲這樣的重定向是臨時的,客戶端應當繼續向原有地址發送之後的請求。只有在Cache-Control或Expires中進行了指定的狀況下,這個響應纔是可緩存的。 新的臨時性的URI應當在響應的Location域中返回。除非這是一個HEAD請求,不然響應的實體中應當包含指向新的URI的超連接及簡短說明。
- 若是這不是一個GET或者HEAD請求,那麼瀏覽器禁止自動進行重定向(第二次 POST 時,環境可能已經發生變化(POST 方法不是冪等)),除非獲得用戶的確認,由於請求的條件可能所以發生變化。
- 注意:雖然RFC 1945和RFC 2068規範不容許客戶端在重定向時改變請求的方法,可是很多現存的瀏覽器將302響應視做爲303響應,而且使用GET方式訪問在Location中規定的URI,而無視原先請求的方法。 所以狀態碼303和307被添加了進來,用以明確服務器期待客戶端進行何種反應。
- 搜索引擎不會更新他們到資源的連接(在 SEO 中,聽說連接果汁不會被髮送到新的 URL)
- 狀態 : 302 Found
303 See Other(查看其餘)
- 對應當前請求的響應能夠在另外一個URI上被找到,**當響應於POST(或PUT / DELETE)接收到響應時,客戶端應該假定服務器已經收到數據,而且應該使用單獨的GET消息發出重定向。這個方法的存在主要是爲了容許由腳本激活的POST請求輸出重定向到一個新的資源。這個新的URI不是原始資源的替代引用。**同時,303響應禁止被緩存。固然,**第二個請求(重定向)可能被緩存。**新的URI應當在響應的Location域中返回。除非這是一個HEAD請求,不然響應的實體中應當包含指向新的URI的超連接及簡短說明。
- 注意:許多HTTP/1.1版之前的瀏覽器不能正確理解303狀態。若是須要考慮與這些瀏覽器之間的互動,302狀態碼應該能夠勝任,由於大多數的瀏覽器處理302響應時的方式偏偏就是上述規範要求客戶端處理303響應時應當作的。
- 狀態 : 303 See Other
304 表示未修改,客戶的緩存資源是最新的,要客戶端使用緩存
- HTTP 304 Not Modified客戶端重定向響應代碼指示不須要從新傳輸請求的資源。這是對緩存資源的隱式重定向。這發生在請求方法是安全的時候,好比一個
GET
或者一個HEAD
請求,或者當請求是有條件的而且使用一個If-None-Match
或者一個If-Modified-Since
標頭時。- 等效
200
OK
響應會包括頭Cache-Control
,Content-Location
,Date
,ETag
,Expires
,和Vary
。- 狀態:304 Not Modified
307 Temporary Redirect(臨時重定向)
- HTTP 307 Temporary Redirect重定向狀態響應代碼指示所請求的資源已暫時移動到由
Location
標題給定的 URL 。- 原始請求的方法和主體被重用來執行重定向的請求。在你想要改變方法的狀況下,改成
GET
使用303
See Other
。當你想給一個PUT
不是上傳資源的方法,而是一個確認信息(如「你成功上傳 XYZ」)時,這頗有用。307
和302
之間的惟一區別在於307
該方法和主體將不會被重定向的請求時改變保證。使用302
,一些老客戶錯誤地將方法改變爲GET
:使用非GET
方法的行爲,而後302
在Web上不可預知,而使用307
的行爲則是可預測的。對於GET
請求,它們的行爲是相同的。- 狀態 : 307 Temporary Redirect
308 Permanent Redirect (永久重定向)
- HTTP 308 Permanent Redirect重定向狀態響應代碼指示所請求的資源已明確移動到
Location
標題給定的 URL 。瀏覽器重定向到這個頁面,搜索引擎更新它們到資源的連接(在 SEO 中,聽說連接汁被髮送到新的 URL)。- 請求方法和主體不會被更改,
301
但有時可能會被錯誤地更改成GET
方法。- 一些 Web 應用程序可能會以非標準方式使用
308 Permanent Redirect
並用於其餘目的。例如,Google 雲端硬盤使用308 Resume Incomplete
響應來向客戶端指示上傳不完整的時間。
400 Bad Request
- 400 因爲語法無效,HTTP400 Bad Request 響應狀態碼指示服務器沒法理解請求。客戶不該未經修改就重複此請求。
- 狀態 400 Bad Request
401 Unauthorized
- HTTP
401 Unauthorized
客戶端錯誤狀態響應代碼指示該請求還沒有應用,由於它缺乏目標資源的有效認證憑證。此狀態與包含有關如何正確受權信息的WWW-Authenticate
標頭一塊兒發送。- 狀態:401 Unauthorized
403 Forbidden
- HTTP
403 Forbidden
客戶端錯誤狀態響應代碼指示服務器理解請求但拒絕受權。這種狀態與此相似401
,但在這種狀況下,從新認證將不會產生任何影響。訪問是永久禁止的而且與應用程序邏輯相關聯(如不正確的密碼)。- 狀態:403 Forbidden
405 Method Not Allowed
- HTTP 405 Method Not Allowed響應狀態碼指示服務器已知請求方法,但已被禁用且沒法使用。這兩個強制性方法,
GET
和HEAD
,毫不能被禁用,不該返回該錯誤代碼。- 狀態:405 Method Not Allowed
(Conflict)表示請求的資源與資源的當前狀態發生衝突
(Gone)表示服務器上的某個資源被永久性的刪除
500 內部服務器錯誤,服務器遇到一個錯誤,使其沒法爲請求提供服務
503 服務器正忙,服務器超時
使用301的場景:(通常是資源位置永久更改)
302的場景:(通常是普通的重定向需求:臨時跳轉)
未登陸前先使用302重定向到登陸頁面,登陸成功後再跳回到原來請求的頁面
好比我未登陸京東前我就訪問京東的我的界面https://home.jd.com/,而後就會重定向到登陸界面,響應的狀態碼爲302,而且返回了location爲登陸界面的url,而且附帶了ReturnUrl方便咱們登陸後跳回到https://home.jd.com/
有時候須要自動刷新頁面,好比5秒後回到訂單詳細頁面之類。
系統進行升級或者切換某些功能時,須要臨時更換地址
像微博之類的使用短域名,用戶瀏覽後須要重定向到真實的地址之類。
例如我訪問一個微博的秒拍視頻連接:t.cn/RuUMBnI,而後重…
電腦端與移動端的轉換
好比我訪問網頁端頁面https://www.taobao.com/,302重定向到了移動端頁面m.taobao.com
303 幾乎沒有,通常就是用302
307的場景
不多用,與302相似,只不過是針對POST方法的請求不容許更改方法
308的場景
不多用,與301相似,只不過是針對POST方法的請求不容許更改方法
303和307的存在,歸根結底是因爲POST方法的非冪等屬性引發的。
308 的存在,返回時301對於某些使用HTTP/1.0協議的瀏覽器,當它們發送的POST請求獲得了一個301響應的話,接下來的重定向請求將會變成GET方式。
301/302/303/307/308的區別 及注意點
- 301,302是http1.0的內容,30三、30七、308是http1.1的內容。
- 301和302原本在規範中是不容許重定向時改變請求方法的(將POST改成GET),可是許多瀏覽器卻容許重定向時改變請求方法(這是一種不規範的實現)。
- 301表示搜索引擎在抓取新內容的同時也將舊的網址交換爲重定向以後的網址;302表示舊地址A的資源還在(仍然能夠訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。
- 由於301與302的區別,因此致使產生302網址劫持,故不建議使用302重定向(然而瀏覽器默認是使用302重定向)
301請求碼進行跳轉被谷歌認爲是將網站地址由 HTTP 遷移到 HTTPS的最佳方法, 可是淘寶就是 302跳轉
實體應該包含一個帶有指向新URI的超連接的短超文本註釋
since many pre-HTTP/1.1 user agents do not understand the *** status.
401 和 403 的區別
- 401 用於認證,而不是受權。接收到401響應時。 服務器會告訴您,「您沒有通過身份驗證——或者根本沒有通過身份驗證,或者身份驗證不正確——可是請從新進行身份驗證,而後重試。」爲了幫助您解決問題,它將始終包含描述如何進行身份驗證的www-authenticate頭。
- 爲了得到受權,我使用403禁止響應。它是永久的,它與個人應用程序邏輯有關,它比401更具體。 服務器收到403的響應後會告訴您:「對不起。我知道你是誰——我相信你說你是誰——但你只是沒有訪問這個資源的權限。若是你向系統管理員友好地詢問,你可能會獲得許可。但在你的困境改變以前,請不要再打擾我。」
- 對於認證丟失或不正確的狀況,應使用401未經受權響應,而且當用戶通過認證但未被受權對給定資源執行請求的操做時,應隨後使用403禁止響應。
長連接 :就是數據傳輸完成了保持TCP鏈接不斷開(不發RST包、不四次握手),等待在同域名下繼續用這個通道傳輸數據;相反的就是短鏈接。
http 1.0中默認是關閉的,須要在http頭加入"Connection: Keep-Alive",才能啓用Keep-Alive。
http 1.1中默認啓用Keep-Alive,若是加入"Connection: close ",才關閉。
是否能完成一個完整的Keep-Alive鏈接就看服務器設置狀況。
優勢
能夠報告錯誤而沒必要關閉TCP鏈接
errors can be reported without the penalty of closing the TCP connection
(1) 長鏈接的數據傳輸完成識別 —— 使用長鏈接以後,客戶端、服務端怎麼知道本次傳輸結束呢?(如何判斷http消息的大小、消息的數量)?
Conent-Length
靜態頁面或圖片等
Conent-Length表示實體內容長度,客戶端(服務器)能夠根據這個值來判斷數據是否接收完成。
Transfer-Encoding
動態頁面 等
即若是要一邊產生數據,一邊發給客戶端,服務器就須要使用"Transfer-Encoding: chunked"這樣的方式來代替Content-Length。
服務器是不可能預先知道內容大小,可使用Transfer-Encoding:chunk模式來傳輸數據了。chunk編碼將數據分紅一塊一塊的發生。Chunked編碼將使用若干個Chunk串連而成,由一個標明長度爲0的chunk標示結束。
使用了HTTP長鏈接(HTTP persistent connection )以後的好處,包括可使用HTTP 流水線技術,它是指,在一個TCP鏈接內,(多條請求放入隊列)當第一條請求發往服務器的時候,第二第三條請求也能夠開始發送了,在高延時網絡條件下,這樣作能夠下降網絡的環回時間,提升性能。
限制
POST
請求。第一個請求耗費了服務器不少的處理時間,那麼後面的請求都要等待第一個處理完,也就出現了線頭阻塞。
request 頭
response 頭
referer 當前頁面 對html的請求來自上一個頁面的 url, ajax請求是當前的url
HTTP 請求消息頭部實例:
Host:rss.sina.com.cn
User-Agent:Mozilla/五、0 (Windows; U; Windows NT 五、1; zh-CN; rv:一、八、一、14) Gecko/20080404 Firefox/二、0、0、14
Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0、9,text/plain;q=0、8,image/png,*/*;q=0、5
Accept-Language:zh-cn,zh;q=0、5
Accept-Encoding:gzip,deflate
Accept-Charset:gb2312,utf-8;q=0、7,*;q=0、7
Keep-Alive:300
Connection:keep-alive
Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW <-- Cookie
If-Modified-Since:Sun, 01 Jun 2008 12:05:30 GMT
Cache-Control:max-age=0
複製代碼
HTTP 響應消息頭部實例:
Status:OK - 200 <-- 響應狀態碼,表示 web 服務器處理的結果。
Date:Sun, 01 Jun 2008 12:35:47 GMT
Server:Apache/二、0、61 (Unix)
Last-Modified:Sun, 01 Jun 2008 12:35:30 GMT
Accept-Ranges:bytes
Content-Length:18616
Cache-Control:max-age=120
Expires:Sun, 01 Jun 2008 12:37:47 GMT
Content-Type:application/xml
Age:2
X-Cache:HIT from 236-4一、D0707195一、sina、com、cn <-- 反向代理服務器使用的 HTTP 頭部
Via:1.0 236-41.D07071951.sina.com.cn:80 (squid/2.6.STABLE13)
Connection:close
複製代碼
影響一個HTTP網絡請求的因素主要有兩個:帶寬和延遲。
HTTP1.0只是使用一些較爲簡單的網頁上和網絡請求上
緩存處理
帶寬優化及網絡鏈接的使用
錯誤通知的管理,在HTTP1.1中新增了24個錯誤狀態響應碼,如
Host頭處理
長鏈接,HTTP 1.1支持長鏈接(Persistent Connection)和請求的流水線(Pipelining)處理,在一個TCP鏈接上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲,在HTTP1.1中默認開啓Connection: keep-alive,必定程度上彌補了HTTP1.0每次請求都要建立鏈接的缺點。
google提出了SPDY的方案,優化了HTTP1.X的請求延遲,解決了HTTP1.X的安全性 , SPDY位於HTTP之下,TCP和SSL之上,這樣能夠輕鬆兼容老版本的HTTP協議(將HTTP1.x的內容封裝成一種新的frame格式),同時可使用已有的SSL功能。
具體優化以下:
多路複用,針對HTTP高延遲的問題,SPDY優雅的採起了多路複用(multiplexing)。多路複用經過多個請求stream共享一個tcp鏈接的方式,解決了HOL blocking的問題,下降了延遲同時提升了帶寬的利用率。
請求優先級(request prioritization)。多路複用帶來一個新的問題是,在鏈接共享的基礎之上有可能會致使關鍵請求被阻塞。SPDY容許給每一個request設置優先級,這樣重要的請求就會優先獲得響應。 好比瀏覽器加載首頁,首頁的html內容應該優先展現,以後纔是各類靜態資源文件,腳本文件等加載,這樣能夠保證用戶能第一時間看到網頁內容。
header壓縮。前面提到HTTP1.x的header不少時候都是重複多餘的。選擇合適的壓縮算法能夠減少包的大小和數量。
基於HTTPS的加密協議傳輸,大大提升了傳輸數據的可靠性。
把客戶端所須要的資源伴隨着index.html一塊兒發送到客戶端,省去了客戶端重複請求的步驟。正由於沒有發起請求,創建鏈接等操做,因此靜態資源經過服務端推送的方式能夠極大地提高速度。
HTTP2.0能夠說是SPDY的升級版(其實本來也是基於SPDY設計的),可是,HTTP2.0 跟 SPDY 仍有不一樣的地方。 HTTP2.0和SPDY的區別:
要實現斷點續傳的功能,一般都須要客戶端記錄下當前的下載進度,並在須要續傳的時候通知服務端本次須要下載的內容片斷。
HTTP1.1協議(RFC2616)中定義了斷點續傳相關的HTTP頭 Range和Content-Range字段
示例 :
- 客戶端下載一個1024K的文件,已經下載了其中512K
- 網絡中斷,客戶端請求續傳,所以須要在HTTP頭中申明本次須要續>傳的片斷:
Range:bytes=512000-
這個頭通知服務端從文件的512K位置開始傳輸文件- 服務端收到斷點續傳請求,從文件的512K位置開始傳輸,而且在HTTP頭中增長:
Content-Range:bytes 512000-/1024000
此時服務端返回的HTTP狀態碼應該是206,而不是200。
問題
(1)終端發起續傳請求時,URL對應的文件內容在服務端已經發生變化,此時續傳的數據確定是錯誤!
- 此時咱們須要有一個標識文件惟一性的方法。在RFC2616中也有相應的定義,好比實現Last-Modified來標識文件的最後修改時間,這樣便可判斷出續傳文件時是否已經發生過改動。同時RFC2616中還定義有一個ETag的頭,可使用ETag頭來放置文件的惟一標識,好比文件的MD5值。 終端在發起續傳請求時應該在HTTP頭中申明If-Match 或者If-Modified-Since 字段,幫助服務端判別文件變化。
- 另外RFC2616中同時定義有一個If-Range頭,終端若是在續傳是使用If-Range。**If-Range中的內容能夠爲最初收到的ETag頭或者是Last-Modfied中的最後修改時候。**服務端在收到續傳請求時,經過If-Range中的內容進行校驗
- 校驗一致時返回206的續傳回應,不一致時服務端則返回200迴應,迴應的內容爲新的文件的所有數據。