簡述HTTP協議

身爲開發人員除了應該對咱們所寫的項目需求要了解,以及基本的語言知識,對於HTTP協議也是應該瞭解一下的,由於這些東西與咱們是密不可分的,天天都在和HTTP打交道然而殊不知道它究竟是什麼?這樣說出去是否是很可悲?簡直可歌可泣有沒有...php

http協議:HTTP是一個簡單的請求-響應協議,它一般運行在TCP之上。它指定了客戶端可能發送給服務器什麼樣的消息以及獲得什麼樣的響應。請求和響應消息的頭以ASCII碼形式給出;而消息內容則具備一個相似MIME的格式。這個簡單模型是早期Web成功的有功之臣,由於它使得開發和部署是那麼的直截了當。超文本傳輸協議(HTTP)是用於傳輸諸如HTML的超媒體文檔的應用層協議。它被設計用於Web瀏覽器和Web服務器之間的通訊,但它也能夠用於其餘目的。HTTP遵循經典的客戶端-服務端模型,客戶端打開一個鏈接以發出請求,而後等待它收到服務器端響應。 -- 百度百科html

HTTP是無狀態協議,意味着服務器不會在兩個請求之間保留任何數據(狀態)。在同一個鏈接中,兩個執行成功的請求之間是沒有關係的。這就帶來了一個問題,用戶沒有辦法在同一個網站中進行連續的交互,好比在一個電商網站裏,用戶把某個商品加入到購物車,切換一個頁面後再次添加了商品,這兩次添加商品的請求之間沒有關聯,瀏覽器沒法知道用戶最終選擇了哪些商品。而使用HTTP的頭部擴展,HTTP Cookies就能夠解決這個問題。把Cookies添加到頭部中,建立一個會話讓每次請求都能共享相同的上下文信息,達成相同的狀態。經過上述得出結論,http特色是:無狀態,無鏈接,簡單快速。web

HTTP交互流程

一個鏈接是由傳輸層來控制的,這從根本上不屬於HTTP的範圍。HTTP並不須要其底層的傳輸層協議是面向鏈接的,只須要它是可靠的,或不丟失消息的(至少返回錯誤)。在互聯網中,有兩個最經常使用的傳輸層協議:TCP是可靠的,而UDP不是。所以,HTTP依賴於面向鏈接的TCP進行消息傳遞,但鏈接並非必須的。express

  • TCP:面向鏈接(如打電話要先撥號創建鏈接)
  • UDP:是無鏈接的,即發送數據以前不須要創建鏈接

關於TCPUDP這裏不作多餘贅述,若是想要深刻了解二者之間的優缺點以及區別的話,有時間再詳細的介紹一下。segmentfault

其實HTTP交互流程就是基於TCP鏈接進行消息傳遞的,然而這個鏈接無關緊要,具體交互流程以下圖:瀏覽器

o_http.png

結合上圖詳細說明經歷的過程:緩存

  1. 打開一個TCP鏈接:TCP鏈接被用來發送一條或多條請求,以及接受響應消息。客戶端可能打開一條新的鏈接,或重用一個已經存在的鏈接,或者也可能開幾個新的TCP鏈接連向服務端
  2. 發送一個HTTP報文:HTTP報文(在HTTP/2以前)是語義可讀的。在HTTP/2中,這些簡單的消息被封裝在了幀中,這使得報文不能被直接讀取,可是原理還是相同的
  3. 讀取服務端返回的報文信息,服務器端接收到請求後,進行處理,而後將處理結果響應客戶端(HTTP協議)
  4. 關閉鏈接或者爲後續請求重用鏈接,關閉客戶端和服務器端的鏈接(HTTP1.1後不會當即關閉)

HTTP流水線啓動時,後續請求均可以不用等待第一個請求的成功響應就被髮送。然而HTTP流水線已被證實很難在現有的網絡中實現,由於現有網絡中有不少老舊的軟件與現代版本的軟件共存。所以,HTTP流水線已被在有多請求下表現得更穩健的HTTP/2的幀所取代。安全

HTTP報文

Linux系統下有一個curl指令能夠經過這個命令來觀測一下HTTP的請求過程。服務器

curl -v https://segmentfault.com/

輸入完以後回車就會看到下面這些信息:cookie

o_http.jpg

圖中>開始的是客服端發送給服務端的信息,以<開始的爲服務端返回給客戶端的一些信息。當客戶端發起一個Ajax請求時,瀏覽器會攜帶一些信息發送給服務端,HTTP請求頭提供了關於請求,響應或者其餘的發送實體的信息。請求報文分爲如下幾個部分:

  1. General(請求行)
  2. Request Headers(請求頭)
  3. Response Headers(響應頭)

這三個部分分別承載了服務端以及客戶端所須要的信息,在瀏覽器中種NetWork中能夠查看到其信息內容,接下來就一一介紹一下:

General

這部分主要提供的是一些公用的請求頭信息:

Request URL: https://segmentfault.com/search?q=search
Request Method: GET
Status Code: 200 
Remote Address: 112.126.83.219:443
Referrer Policy: no-referrer-when-downgrade
  • Request URL:請求地址
  • Request Method:請求方式
  • Status Code:狀態碼
  • Remote Address:請求的遠程地址
  • Referrer Policy: 過濾 Referrer 報頭內容

上述信息代表,客戶端向服務器發送一個http請求,其請求地址爲https://segmentfault.com/search?q=search,使用GET方式發起這個請求,請求返回狀態爲200,鏈接的遠程地址爲112.126.83.219:443,過濾報頭採用的是不傳遞Referrer

向前面幾個應該都比較熟悉也通俗易懂,當看到的這的時候內心有一些些的小疑惑Remote Address是什麼?Referrer Policy過濾報頭的規則有哪些?

Remote Address

關於Remote Address遠程鏈接地址,Remote Address表明客戶端的IP,但它的值不是由客戶端提供的,而是服務端根據客戶端的IP指定的,當你的瀏覽器訪問某個網站時,假設中間沒有任何代理,那麼網站的web服務器(Nginx,Apache等)就會把Remote Address設爲你的機器IP,若是你用了某個代理,那麼你的瀏覽器會先訪問這個代理,而後再由這個代理轉發到網站,這樣web服務器就會把Remote Address設爲這臺代理機器的IP。以致於後面的443端口,也簡單的看了一下,443端口即網頁瀏覽端口,主要是用於HTTPS服務,是提供加密和經過安全端口傳輸的另外一種HTTP。在一些對安全性要求較高的網站,好比銀行、證券、購物等,都採用HTTPS服務,這樣在這些網站上的交換信息,其餘人抓包獲取到的是加密數據,保證了交易的安全性。我也沒有作深刻的瞭解,大概就是這個樣子吧。

Referrer Policy

Referrer-Policy的做用就是爲了控制請求頭中referrer的內容,目前是一個候選標準,不過已經有部分瀏覽器支持該標準。目前Referrer-Policy只包含如下幾種值:

解釋
no-referrer 不顯示referrer的任何信息在請求頭中。
no-referrer-when-downgrade 這是默認值。當從https網站跳轉到http網站或者請求其資源時(安全降級HTTPS→HTTP),不顯示referrer的信息,其餘狀況(安全同級HTTPS→HTTPS,或者HTTP→HTTP)則在referrer中顯示完整的源網站的URL信息。
same-origin 表示瀏覽器只會顯示referrer信息給同源網站,而且是完整的URL信息。所謂同源網站,是協議、域名、端口都相同的網站。
origin 表示瀏覽器在referrer字段中只顯示源網站的源地址(即協議、域名、端口),而不包括完整的路徑。
strict-origin 該策略更爲安全些,和origin策略類似,只是不容許referrer信息顯示在從https網站到http網站的請求中(安全降級)。
origin-when-cross-origin 當發請求給同源網站時,瀏覽器會在referrer中顯示完整的URL信息,發個非同源網站時,則只顯示源地址(協議、域名、端口)
strict-origin-when-cross-origin 和origin-when-cross-origin類似,只是不容許referrer信息顯示在從https網站到http網站的請求中(安全降級)。
unsaft-url 瀏覽器老是會將完整的URL信息顯示在referrer字段中,不管請求發給任何網站。

Referrer-Policy值不是固定不變的,而是但是經過程序手動設置,通常都會不會去手動更改除非網頁中不存在一些敏感信息,那就默認使用no-referrer-when-downgrade。這裏就多說了,若是有興趣的能夠調研一下。

Response Headers

這部分存儲的是響應頭信息,當服務端接受到請求,並處理完成以後須要向客戶端作出應答。

cache-control: no-store, no-cache, must-revalidate
content-encoding: gzip
content-type: text/html; charset=UTF-8
date: Fri, 28 Jun 2019 09:32:09 GMT
expires: Thu, 19 Nov 1981 08:52:00 GMT
pragma: no-cache
status: 200
strict-transport-security: max-age=15768000; preload
x-hit: web1
  • cache-control:響應輸出到客戶端後,服務端經過該報文頭告訴客戶端如何控制響應內容的緩存
  • content-encoding:文檔編碼(Encode)方法。只有在解碼以後才能夠獲得Content-Type頭指定的內容類型
  • content-type:文檔類型
  • date:當前的GMT時間,能夠用setDateHeader來設置
  • expires:文檔過時時間,文檔到期後則再也不緩存
  • pragma:設置消息頭,(no-cache)強制清除緩存
  • status:服務器響應狀態碼
  • strict-transport-security:安全功能,它告訴瀏覽器只能經過HTTPS訪問當前資源,而不是HTTP
Request Headers

這部分承載的是請求頭的信息,當客戶端向服務端發送請求時,須要傳遞給服務端的信息內容。

:authority: segmentfault.com
:method: GET
:path: /search?q=1
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9
cookie: e23800c454aa573c0ccb16b52665ac26=1561712973
referer: https://segmentfault.com/
user-agent: Chrome/75.0.3770.100 Safari/537.
  • :authority:請求權限(HTTP2.0)
  • :method:請求方式(HTTP2.0)
  • :path:請求地址(HTTP2.0)
  • :scheme:請求協議(HTTP2.0)
  • accept:指定客戶端能夠接受的內容類型,好比文本,圖片,應用等等,內容的前後排序表示客戶端接收的前後次序,每種類型之間用逗號隔開。
  • accept-encoding:客戶端接收編碼類型,一些網絡壓縮格式:Accept-Encoding: gzip, deflate, sdch。相對來講,deflate是一種過期的壓縮格式,如今經常使用的是gzip
  • accept-language:客戶端能夠接受的語⾔言類型,參數值規範和 accept的很像。通常就接收中文和英文,有其餘語言需求自行添加。
  • cookie:一樣是一個比較關鍵的字段,Cookie是 client 請求服務器時,服務器會返回一個鍵值對樣的數據給瀏覽器,下一次瀏覽器再訪問這個域名下的網頁時,就須要攜帶這些鍵值對數據在 Cookie中,用來跟蹤瀏覽器用戶的訪問先後路徑。
  • referer:瀏覽器上次訪問的網頁url,uri。因爲http協議的無記憶性,服務器可從這裏瞭解到客戶端訪問的先後路徑,並作一些判斷,若是⼀次訪問的 url 不能從前一次訪問的頁面上跳轉得到, 在必定程度上說明了請求頭有可能僞造。
  • user-agent:中文名用戶代理,服務器今後處知道客戶端的操做系統類型和版本,電腦CPU類型,瀏覽器 種類版本,瀏覽器渲染引擎,等等。

accept-language共分爲下列幾種:

zh-CN:中文簡體大陸
zh:其餘中文
en-US:英語美語
en:其餘英語

Cookie就是存儲在客戶端的一小段文本,由於cookie是存儲在客戶端瀏覽器中的,Cookie不能做爲代碼執行,也不會傳送病毒,且爲你所專有,並只能由提供它的服務器來讀取。保存的信息片段以名/值對(name-value)的形式儲存,一個名/值對僅僅是一條命名的數據。一個網站只能取得它放在你的電腦中的信息,它沒法從其它的cookie文件中取得信息,也沒法獲得你的電腦上的其它任何東西。

const express = require('express');
const cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser('sign'));
app.get('/set', function(req, res) {
    res.cookie('name', 'TracyYu', {maxAge: 9999999, httpOnly: true, signed: true});
    res.send('cookie設置成功');
})
app.get('/get', function(req, res) {
    console.log(req.signedCookies);
    res.send('success')
})
app.listen('3000', function() {
    console.log('3000成功');
})

經過上面代碼中對cookie進行設置以後,用戶訪問/set路由的是時候已經把cookie設置到了瀏覽器的頭部,當用戶訪問/get路由的時候,因爲在瀏覽器中已經設置好cookie,在同屬於一個服務的狀況下是能夠直接獲取到cookie的。固然除了上述所說,經過document也是能夠手動設置cookie的,在客戶端設置的cookie在服務端一樣是也能夠獲取到的。

document.cookie="userId=929";

這樣就將名爲userIdcookie值設置爲了929,如今訪問/get一樣就能拿到在客戶端設置的cookie值了。

請求方式

http中常常用的到的就是getpost兩種,在開發過程當中會遵循RESTful接口風格,這是一種如今比較流行的接口風格,使用這種接口風格須要用到一些其餘的請求方式,http請求方式一共有8種。

請求方式 描述
OPTIONS 容許客戶端查看服務器的性能,服務器針對特定資源所支持的HTTP請求方法,也能夠利用向web服務器發送‘*’的請求來測試服務器的功能性
HEAD 向服務器索與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠再沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應小消息頭中的元信息。
GET 向特定的資源發出請求。它本質就是發送一個請求來取得服務器上的某一資源。資源經過一組HTTP頭和呈現數據(如HTML文本,或者圖片或者視頻等)返回給客戶端。GET請求中,永遠不會包含呈現數據。
POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。
PUT 向指定資源位置上傳其最新內容
DELETE 請求服務器刪除Request-URL所標識的資源
TRACE 回顯服務器收到的請求,主要用於測試或診斷
CONNECT HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。

HTTP定義了與服務器交互的不一樣方法,最基本的方法是GETPOST(開發關心的只有GET請求和POST請求)。

GET和POST長度的限制問題
GET POST
GET是經過URL提交數據,所以GET可提交的數據量就跟URL所能達到的最大長度有直接關係 HTTP協議沒有對POST進行任何限制,通常是受服務器配置限制或者內存大小
HTTP協議對URL長度是沒有限制的;限制URL長度大多數是瀏覽器或者服務器的配置參數 PHP下能夠修改php.conf的postmaxsize來設置POST的大小

其實這裏有一個很大的誤區,http協議並未規定GETPOST的長度限制,GET的最大長度限制是由於瀏覽器和web服務器限制了URL的長度,不一樣的瀏覽器和web服務器,限制的最大長度不同,要支持IE,則最大長度爲2083byte,若支持Chrome,則最大長度8182byte,首先即便GET有長度限制,也是限制的整個URL的長度,而不只僅是參數值數據長度。

GET和POST的安全性
  1. GET是經過URL方式請求,能夠直接看到,明文傳輸
  2. POST是經過請求header請求,能夠開發者工具或者抓包能夠看到,一樣也是明文的
  3. GET請求會保存在瀏覽器歷史紀錄中,還可能會保存在Web的日誌中

GET請求指定資源的表示形式。注意,GET不該該用於產生反作用的操做,好比在web應用程序中使用它執行操做。緣由之一是GET可能被機器人或爬行器任意使用,它們不須要考慮請求應該引發的反作用。POST將要處理的數據(例如,從HTML表單)提交給標識的資源。數據包含在請求體中。這可能會致使建立新資源或更新現有資源,或者二者兼而有之。使用HTTP協議的服務不該該使用基於GET的表單來提交敏感數據,由於這會致使這些數據在Request-URI中編碼。許多現有服務器,代理和用戶代理會將請求URI記錄在第三方可能看到的某個位置。服務器可使用基於POST的表單提交。

GET與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. 服務器返回200OK響應

總結

本來想說一些狀態碼相關的東西,可是簡單的看了一下,好像又沒有什麼好說的,百度百科說的也很清楚,就不在文章裏面贅述了。

簡單的對http協議作了一些小的介紹與總結,若是文章中有哪些地方有問題,請在下方留言指正,我會盡快作出改正。

相關文章
相關標籤/搜索