這篇文章主要是我平時在學習HTTP過程當中看到的一些知識點,如今把他們總結成一篇文章,創建一個本身的知識體系,全是乾貨。另外,推薦一本很是棒的HTTP書——《圖解HTTP》,這本書圖文並茂,挺有趣的。
javascript
HTTP是基於TCP/IP協議的應用層協議,用於客戶端和服務器之間的通訊,默認80端口。咱們按照他的發展歷程的時間順序開始說。css
1990年提出的,是最先期的版本,只有一個命令GET。html
1996年5月提出的。html5
缺點
:每一個TCP鏈接只能發送一個請求。解決方法
:Connection:keep-alive 1997年1月提出,如今使用最普遍的。java
長鏈接
:TCP鏈接默認不關閉,能夠被多個請求複用。對於同一個域名,大多數瀏覽器容許同時創建6個持久鏈接。默認開啓Connection:keep-alive。
jquery
管道機制
:在同一個TCP鏈接裏,能夠同時發送多個請求。可是服務器仍是要按照請求的順序進行響應,會形成「隊頭阻塞」。
web
HTTP首部分爲請求報文和響應報文。它們的格式以下所示:
ajax
其中首部字段又分爲不少種,咱們先看通用首部字段,這是請求報文和響應報文種都會使用的首部。數據庫
一、Cache-Control
:操做緩存的工做機制
json
參數:
- public:明確代表其餘用戶也能夠利用緩存
- private:緩存只給特定的用戶
- no-cache:客戶端發送這個指令,表示客戶端不接收緩存過的響應,必須到服務器取;服務器返回這個指令,指緩存服務器不能對資源進行緩存。實際上是不緩存過時資源,要向服務器進行有效期確認後再處理資源。
- no-store:指不進行緩存
- max-age:緩存的有效時間(相對時間)
二、Connection
:
- Connection:keep-Alive (持久鏈接)
- Connection:再也不轉發的首部字段名
三、Date
:代表建立http報文的日期和時間
四、Pragma
:兼容http1.0,與Cache-Control:no-cache含義同樣。但只用在客戶端發送的請求中,告訴全部的中間服務器不返回緩存。形式惟一:Pragma:no-cache
五、Trailer
:會事先說明在報文主體後記錄了哪些首部字段,該首部字段能夠應用在http1.1版本分塊傳輸編碼中。
六、Transfer-Encoding
:chunked (分塊傳輸編碼), 規定傳輸報文主體時採用的編碼方式,http1.1的傳輸編碼方式只對分塊傳輸編碼有效
七、Upgrade
:升級一個成其餘的協議,須要額外指定Connection:Upgrade。服務器可用101狀態碼做爲相應返回。
八、Via
:追蹤客戶端和服務器之間的請求和響應報文的傳輸路徑。能夠避免請求迴環發生,因此在通過代理時必需要附加這個字段。
一、Accept:通知服務器,用戶代理可以處理的媒體類型及媒體類型的相對優先級 q表示優先級的權重值,默認爲q = 1.0,範圍是0~1(可精確到小數點後3位,1爲最大值) 當服務器提供多種內容時,會先返回權重值最高的媒體類型
二、Accept-Charset:支持的字符集及字符集的相對優先順序,跟Accept同樣,用q來表示相對優先級。這個字段應用於內容協商機制的服務器驅動協商。
三、Accept-Encoding:支持的內容編碼及內容編碼的優先級順序,q表示相對優先級。 內容編碼:gzip、compress、deflate、identity(不執行壓縮或者不會變化的默認編碼格式)。 可使用*做爲通配符,指定任意的編碼格式。
四、Accept-Language:可以處理的天然語言集,以及相對優先級。
101 協議升級
,主要用於升級到websocket,也能夠用於http2
200 OK
204 No content
,服務器成功處理請求,可是返回的響應報文中不含實體的主體部分
206 Partial Content
,表示客戶端像服務器進行了範圍請求(Content-Range字段),服務器成功返回指定範圍的實體內容
301 永久性重定向
,表示請求的資源已經被分配了新的url,舊地址之後都不能再訪問了,服務器會返回location字段,包含的是新的地址。
302 臨時性重定向
,表示請求的資源臨時移動到一個新地址
注意:儘可能使用301跳轉,由於302會形成網址劫持,可能被搜索引擎判爲可疑轉向,甚至認爲是做弊。
緣由:從網站A(網站比較爛)上作了一個302跳轉到網站B(搜索排名很靠前),這時候有時搜索引擎會使用網站B的內容,但卻收錄了網站A的地址,這樣在不知不覺間,網站B在爲網站A做貢獻,網站A的排名就靠前了。
303 See Other
,與302功能相同,可是它明確規定客戶端應採用GET方法獲取資源
304 未修改
,協商緩存中返回的狀態碼
307 臨時重定向
,與302功能相同,但規定不能從POST變成GET
當30一、30二、303響應狀態碼返回時,幾乎全部瀏覽器都會把post改爲get,並刪除請求報文內的主體,以後請求會自動再次發送。然而30一、302標準是禁止將post方法改變成get方法的,但實際使用時你們都會這麼作。因此須要307。
400 Bad Request
,表示請求報文中存在語法錯誤。當錯誤發生時,須要修改請求的內容再次發送請求
401 unauthorized
,表示發送的請求須要有經過HTTP認證(BASIC認證、DIGEST認證)的認證信息。若是以前已經進行過一次請求,表示用戶認證失敗。
403 禁止
,表示拒絕對請求資源的訪問
404 Not Found
,代表服務器上沒法找到請求的資源
500 Internet Server Error
,該狀態碼錶示服務器在執行請求時發生了錯誤
500 Service Unavailable
,表示服務器暫時處於超負荷或者處於停機維護狀態,如今沒法處理請求
2009年穀歌提出。
SPDY結構
:新增特性
:缺點
:html5新提出來的,是web瀏覽器與web服務器之間的全雙工通訊標準。主要是爲了解決ajax和comet裏的xmlhttprequest附帶的缺陷所引發的問題。
(1)推送功能:服務器可直接發送數據,不須要等待客戶端的請求;
(2)基於TCP傳輸協議,並複用HTTP的握手通道;
(3)支持雙向通訊,用於實時傳輸消息;
(4)更好的二進制支持;
(5)更靈活,更高效。
一、客戶端:發起協議升級請求
GET / HTTP/1.1 `採用HTTP報文格式,只支持get請求`
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade `表示要升級協議`
Upgrade: websocket `表示升級到websocket協議`
Sec-WebSocket-Version: 13 `表示websocket 的版本`
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw== `是一個 Base64 encode 的值,是瀏覽器隨機生成的`
Sec-WebSocket-Protocol:chat, superchat `用來指定一個特定的子協議,一旦這個字段有設置,那麼服務器須要在創建鏈接的響應頭中包含一樣的字段,內容就是選擇的子協議之一。`
複製代碼
二、服務端:響應協議升級
HTTP/1.1 101 Switching Protocols `101表示協議切換==`
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU= `通過服務器確認,而且加密事後的 Sec-WebSocket-Key`
Sec-WebSocket-Protocol:chat `表示最終使用的協議`
複製代碼
Sec-WebSocket-Key 的加密過程爲:
- 將Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
- 經過SHA1計算出摘要,並轉成base64字符串。
三、雙方握手成功後,就是全雙工的通訊了,接下來就是用websocket協議來進行通訊了。
一、ajax輪詢
讓瀏覽器每隔必定的時間就發送一次請求,詢問服務器是否有新信息。
二、長輪詢(Long Poll)
採用的阻塞模式。客戶端發起鏈接後,若是沒消息,服務器不會立刻告訴你沒消息,而是將這個請求掛起(pending),直到有消息才返回。返回完成或者客戶端主動斷開後,客戶端再次創建鏈接,周而復始。Comet就是採用的長輪詢。
三、websocket
WebSocket 是相似 Socket 的TCP長鏈接通信模式。一旦 WebSocket 鏈接創建後,後續數據都以幀序列的形式傳輸。並且瀏覽器和服務器就能夠隨時主動發送消息給對方,是全雙工通訊。
優勢:在海量併發及客戶端與服務器交互負載流量大的狀況下,極大的節省了網絡帶寬資源的消耗,有明顯的性能優點,且客戶端發送和接受消息是在同一個持久鏈接上發起,實時性優點明顯。
2015年發佈,它是基於SPDY的,如下是它的一些新特性:
一、 二進制分幀
:
http/1.x 是一個超文本協議,而 http2 是一個二進制協議,被稱之爲二進制分幀。 二進制格式在協議的解析和優化擴展上帶來更多的優點和可能。
協議格式爲幀,幀由 Frame Header(頭信息幀)和 Frame Payload(數據幀)組成,以下所示:
二、頭部壓縮 HPACK
:
請求和響應首部壓縮,客戶端和服務端共同維護一張頭信息表,全部字段存入這個表,生成一個索引號,經過發送索引號提升速度。HPACK壓縮會通過兩步:
- 傳輸的value,會通過一遍Huffman coding來節省資源;
- 爲了server和client同步, 兩邊都須要保留一份Header list, 而且,每次發送請求時,都會檢查更新。
三、服務端推送
:
服務端主動向客戶端推送數據。若是客戶端請求一個html文件,服務端把html文件返回給客戶端以後,還會相應的把html文件中的js、css、圖片推送給客戶端。
四、多路複用
:
只須要創建一個TCP鏈接,瀏覽器和服務器能夠同時發送多個請求或者回應,並且不須要按照順序一一對應,避免了「隊頭阻塞」。
五、數據流
:
當客戶端同時向服務端發起多個請求,那麼這些請求會被分解成一一個的幀,每一個幀都會在一個 TCP 鏈路中無序的傳輸,同一個請求的幀的 Stream Identifier 都是同樣的。當幀到達服務端以後,就能夠根據 Stream Identifier 來從新組合獲得完整的請求。
而且規定:客戶端發出的數據流ID爲奇數,服務器發出的ID爲偶數。Stream Identifier (數據流ID)就是用來標識該幀屬於哪一個請求的。
HTTPS = HTTP+加密+認證+完整性保護
它的加密過程是:
下圖是加密過程的圖解,能夠對照着圖片理一遍。
HTTP的緩存分爲強緩存和協商緩存(對比緩存)。
強制緩存
在緩存數據未失效的狀況下,能夠直接使用緩存數據;在沒有緩存數據的時候,瀏覽器向服務器請求數據時,服務器會將數據和緩存規則一併返回,緩存規則信息包含在響應header中。
Expires:緩存過時時間(HTTP1.0)
缺點:生成的是絕對時間,可是客戶端時間能夠隨意修改,會致使偏差。
Cache-Control :HTTP1.1,優先級高於Expires
可設置參數:
private: 客戶端能夠緩存
public: 客戶端和代理服務器均可緩存
max-age=xxx: 緩存的內容將在 xxx 秒後失效
no-cache: 須要使用協商緩存來驗證緩存數據(後面介紹)
no-store: 全部內容都不會緩存,強制緩存,對比緩存都不會觸發
Expires和Cache-Control決定了瀏覽器是否要發送請求到服務器,ETag和Last-Modified決定了服務器是要返回304+空內容仍是新的資源文件。
協商緩存
瀏覽器第一次請求數據時,服務器會將緩存標識與數據一塊兒返回給客戶端,客戶端將兩者備份至緩存數據庫中。再次請求數據時,客戶端將備份的緩存標識發送給服務器,服務器根據緩存標識進行判斷,判斷成功後,返回304狀態碼,通知客戶端比較成功,可使用緩存數據。
Last-Modified
:服務器在響應請求時,告訴瀏覽器資源的最後修改時間。If-Modified-Since
:再次請求服務器時,經過此字段通知服務器上次請求時,服務器返回的資源最後修改時間。
缺點:Last-Modified 標註的最後修改時間只能精確到秒,若是有些資源在一秒以內被屢次修改的話,他就不能準確標註文件的新鮮度了。若是某些資源會被按期生成,當內容沒有變化,但 Last-Modified 卻改變了,致使文件沒使用緩存有可能存在服務器沒有準確獲取資源修改時間,或者與代理服務器時間不一致的情形。
Etag
:給資源計算得出的一個惟一標誌符。If-None-Match
:再次請求服務器時,經過此字段通知服務器客戶端緩存數據的惟一標識。
具體過程以下圖:
解決http的無狀態問題,是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,來實現session的跟蹤。
name、value
:以key/value的形式存在
comment
:說明該cookie的用處
domain
:能夠訪問該cookie的域名
Expires/maxAge
:cookie失效時間。負數:臨時cookie,關閉瀏覽器就失效;0:表示刪除cookie,默認爲-1
path
:能夠訪問此cookie的頁面路徑
size
:cookie的大小
secure
:是否以https協議傳輸
version
:該cookie使用的版本號,0遵循Netscape規範,大多數用這種,1遵循W3C規範
HttpOnly
:此屬性爲true,則只有在http請求頭中會帶有此cookie的信息,而不能經過document.cookie來訪問此cookie,能防止XSS攻擊。
客戶端請求服務器時,若是服務器須要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。而客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求服務器時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器經過檢查該Cookie來獲取用戶狀態。
cookie的同源是域名相同,忽略協議和端口,不可跨域。
session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據能夠保存在集羣、數據庫、文件中。
session的運行依賴session id,而session id是存在cookie中的
session機制原理:
當客戶端請求建立一個session的時候,服務器會先檢查這個客戶端的請求裏是否已包含了一個session標識——sessionId。若是已包含這個sessionId,則說明之前已經爲此客戶端建立過session,服務器就按照sessionId把這個session檢索出來使用(若是檢索不到,可能會新建一個。若是客戶端請求不包含sessionId,則爲此客戶端建立一個session而且生成一個與此session相關聯的sessionId。
使用URL重寫技術來進行會話跟蹤。在 url 中傳遞 session id,即每次HTTP交互,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識別用戶。
cookie 數據存放在客戶的瀏覽器上,session數據放在服務器上;
cookie 不是很安全,別人能夠分析存放在本地的 cookie 並進行 cookie 欺騙考慮到安全應當使用 session;
session 會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能考慮到減輕服務器性能方面,應當使用 cookie;
單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個 cookie。
鑑於上述區別咱們建議:
(1)將登錄信息等重要信息存放爲 session;
(2)其餘信息若是須要保留,能夠放在 cookie 中。
共同點:都是保存在瀏覽器端、且同源的。
數據存儲方面
存儲數據大小
數據存儲有效期
做用域不一樣
跨域產生的緣由,是由於受到同源策略的限制。同源策略指的是協議、域名、端口不相同。這裏我將介紹三種跨域的方式:JSONP、CORS(跨域資源共享)、document.domain + iframe。
1. 原理
動態插入script標籤(由於script標籤不受同源策略的限制),經過插入script標籤引入一個js文件,這個js文件加載成功以後會執行咱們在url中指定的回調函數,而且會把咱們須要的json數據做爲參數傳入。
2. 實現
(1)原生實現:
var script = document.createElement('script');
script.type = 'text/javascript';
// 傳參並指定回調執行函數爲onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回調函數
function onBack(res) {
alert(JSON.stringify(res));
}
//服務端返回以下(返回時即執行全局函數):
onBack({"status": true, "user": "admin"})
複製代碼
(2)jquery ajax:
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 請求方式爲jsonp
jsonpCallback: "onBack", // 自定義回調函數名
data: {}
});
複製代碼
1. 原理
服務器在響應頭中設置相應的選項,瀏覽器若是支持這種方法的話就會將這種跨站資源請求視爲合法,進而獲取資源。
2. 實現
CORS分爲簡單請求和複雜請求,簡單請求指的是:
(1)請求方法是如下三種方法之一:HEAD、GET、POST;
(2)HTTP的頭信息不超出如下幾種字段: Accept、Accept-Language、Content-Language、Last-Event-ID、 Content-Type(只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain)。
其餘狀況就是非簡單請求了。
(1)請求頭
:
Origin: http://www.domain.com
複製代碼
(2)響應頭
:
Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Credentials: true `是否容許傳送cookie`
Access-Control-Expose-Headers: FooBar `CORS請求時,只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。若是想拿到其餘字段,就必須指定。`
複製代碼
(3)另外,ajax請求中
,若是要發送Cookie,Access-Control-Allow-Origin就不能設爲星號,必須指定明確的、與請求網頁一致的域名,還要設置如下內容:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
複製代碼
(1)預檢請求
:
OPTIONS /cors HTTP/1.1 `OPTIONS請求是用來詢問的`
Origin: http://www.domian.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
複製代碼
(2)響應頭
:
Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Methods: GET, POST, PUT `服務器支持的全部跨域請求的方法`
Access-Control-Allow-Headers: X-Custom-Header `服務器支持的全部頭信息字段,不限於瀏覽器在"預檢"中請求的字段。`
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000 `指定本次預檢請求的有效期,單位爲秒`
複製代碼
(3)以後的步驟就同簡單請求了
。
這是CORS的整個流程圖:
與JSOP的比較:
JSONP只支持GET請求,CORS支持全部類型的HTTP請求。JSONP的優點在於支持老式瀏覽器,以及能夠向不支持CORS的網站請求數據。
複製代碼
此方案僅限主域相同,子域不一樣的跨域應用場景。
1.原理
兩個頁面都經過js強制設置document.domain爲基礎主域,就實現了同域。
2.實現
(1)父窗口:(www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>
複製代碼
(2)子窗口:(child.domain.com/b.html)
<script>
document.domain = 'domain.com';
// 獲取父窗口中變量
alert('get js data from parent ---> ' + window.parent.user);
</script>
複製代碼