關(guān)于Http協(xié)議一些重要概念

一、Http狀態(tài)碼

狀態(tài)碼的職責(zé)是當(dāng)客戶端向服務(wù)器端發(fā)送請求時,描述返回的請求結(jié)果。借助狀態(tài)碼,用戶可以知道服務(wù)器端是正常處理了請求,還是出現(xiàn)了錯誤。

image

1.狀態(tài)碼的分類

image

2.常見的狀態(tài)碼

僅記錄在 RFC2616 上的 HTTP 狀態(tài)碼就達(dá) 40 種,若再加上 WebDAV(RFC4918、5842)和附加 HTTP 狀態(tài)碼 (RFC6585)等擴(kuò)展,數(shù)量就達(dá) 60 余種。別看種類繁多,實際上經(jīng)常使用的大概只有 14 種。接下來,我們就介紹一下這些具有代表性的 14 個狀態(tài)碼。

  • 200 表示從客戶端發(fā)來的請求在服務(wù)器端被正常處理了。
  • 204 表示請求處理成功,但沒有資源返回。
  • 206 表示客戶端進(jìn)行了范圍請求,而服務(wù)器成功執(zhí)行了這部分的GET請求。
    這種情況經(jīng)常發(fā)生在客戶端繼續(xù)請求一個未完成的下載的時候(比如當(dāng)客戶端加載一個體積較大的嵌入文件,比如視頻或PDF文件),或者是客戶端嘗試實現(xiàn)帶寬遏流的時候。
  • 301 表示永久性重定向。該狀態(tài)碼表示請求的資源已被分配了新的URI,以后應(yīng)使用資源現(xiàn)在所指的URI。
  • 302 表示臨時性重定向。該狀態(tài)碼表示請求的資源已被分配了新的URI,希望用戶(本次)能使用新的URI訪問。和301相似,但302表示的資源不是永久移動,只是臨時性的。換句話說,已移動的資源對應(yīng)的URI將來還有可能發(fā)生變化,比如,用戶把URI保存為書簽,但不會像301狀態(tài)碼出現(xiàn)時那樣更新書簽,而是仍舊保留返回302狀態(tài)碼的頁面對應(yīng)的URI。
  • 303 表示由于請求對應(yīng)的資源存在著另一個URI,應(yīng)使用GET方法定向獲取請求的資源。
    303和302狀態(tài)碼有著相同的功能,但是303明確表示客戶端應(yīng)當(dāng)采用get方法獲取資源,這點與302狀態(tài)碼有區(qū)別。 比如,當(dāng)使用POST方法訪問CGl程序,其執(zhí)行后的處理結(jié)果是希望客戶端能以GET方法重定向到另一個URI上去時,返回303狀態(tài)碼。
    當(dāng)301、302、303響應(yīng)狀態(tài)碼返回時,幾乎所有瀏覽器都會把post改成get,并刪除請求報文內(nèi)的主體,之后請求會自動再次發(fā)送。
    301、302標(biāo)準(zhǔn)是禁止將post方法改變成get方法的,但實際使用時大家都會這么做
    。
  • 304 表示客戶端發(fā)送附帶條件的請求時(指采用GET方法的請求報文中包含if-matched,if-modified-since,if-none-match,if-range,if-unmodified-since任一個首部)服務(wù)器端允許請求訪問資源,但因發(fā)生請求未滿足條件的情況后,直接返回304Modified(服務(wù)器端資源未改變,可直接使用客戶端未過期的緩存)
  • 307 表示臨時重定向。該狀態(tài)碼與302有相同的含義。盡管302標(biāo)準(zhǔn)禁止post變化get,但實際使用時大家不遵守。 307會遵照瀏覽器標(biāo)準(zhǔn),不會從post變?yōu)間et。但是對于處理響應(yīng)時的行為,各種瀏覽器有可能出現(xiàn)不同的情況。303和307是HTTP1.1新加的服務(wù)器響應(yīng)文檔的狀態(tài)碼,它們是對HTTP1.0中的302狀態(tài)碼的細(xì)化,主要用在對非GET、HEAD方法的響應(yīng)上。
  • 400 表示請求報文中存在語法錯誤。當(dāng)錯誤發(fā)生時,需修改請求的內(nèi)容后再次發(fā)送請求。
  • 401 表示未授權(quán)(Unauthorized),當(dāng)前請求需要用戶驗證
  • 403 表示對請求資源的訪問被服務(wù)器拒絕了
  • 404 表示服務(wù)器上無法找到請求的資源。除此之外,也可以在服務(wù)器端拒絕請求且不想說明理由時使
    用。
  • 500 表示服務(wù)器端在執(zhí)行請求時發(fā)生了錯誤。也有可能是Web應(yīng)用存在的bug或某些臨時的故障。
  • 503 表示服務(wù)器暫時處于超負(fù)載或正在進(jìn)行停機(jī)維護(hù),現(xiàn)在無法處理請求。

狀態(tài)碼和狀況的不一致,不少返回的狀態(tài)碼響應(yīng)都是錯誤的,但是用戶可能察覺不到這點。比如Web應(yīng)用程序內(nèi)部發(fā)生錯誤,
狀態(tài)碼依然返回200 OK,這種情況也經(jīng)常遇到。

二、TCP連接

image

TCP建立一個連接,首先需要進(jìn)行三次握手。

1.三次握手

首先Client端發(fā)送連接請求報文,Server段接受連接后回復(fù)ACK報文,并為這次連接分配資源Client端接收到ACK報文后也向Server段發(fā)生ACK報文,并分配資源,這樣TCP連接就建立了。

1.客戶端發(fā)送一個帶SYN=1,Seq=X的數(shù)據(jù)包到服務(wù)器端口

2.服務(wù)器發(fā)回一個帶SYN=1, ACK=X+1, Seq=Y的響應(yīng)包以示傳達(dá)確認(rèn)信息

3.客戶端再回傳一個帶ACK=Y+1, Seq=Z的數(shù)據(jù)包,代表“握手結(jié)束”

2.為啥需要三次握手

謝希仁著《計算機(jī)網(wǎng)絡(luò)》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤”。

client發(fā)出的第一個連接請求報文段并沒有丟失,而是在某個網(wǎng)絡(luò)結(jié)點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達(dá)server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認(rèn)為是client再次發(fā)出的一個新的連接請求。于是就向client發(fā)出確認(rèn)報文段,同意建立連接。假設(shè)不采用“三次握手”,那么只要server發(fā)出確認(rèn),新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求,因此不會理睬server的確認(rèn),也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運(yùn)輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況,client不會向server的確認(rèn)發(fā)出確認(rèn)。server由于收不到確認(rèn),就知道client并沒有要求建立連接。

三、長連接

在HTTP/1.0中,默認(rèn)使用的是短連接。也就是說,瀏覽器和服務(wù)器每進(jìn)行一次HTTP操作,就建立一次連接,但任務(wù)結(jié)束就中斷連接。

從 HTTP/1.1起,默認(rèn)使用長連接,用以保持連接特性。使用長連接的HTTP協(xié)議,會在響應(yīng)頭有加入這行代碼:Connection:keep-alive,可以設(shè)置關(guān)閉時間。
由于瀏覽器的限制,同一個域下最多只能建立6個TCP連接(可以復(fù)用)。我們通常使用子域名來減少所有資源在只有一個連接時的產(chǎn)生的排隊延遲。

image

HTTP/2.0 時代擁有了“多路復(fù)用”功能,意思是:在一條連接上,可以同時發(fā)起無數(shù)個請求,并且響應(yīng)可以同時返回。HTTP2.0通信都在一個連接上完成,這個連接可以承載任意數(shù)量的雙向數(shù)據(jù)流。
對一個域名,只需要開啟一條 TCP 連接,請求都在這條 TCP 連接上干活。

長連接的意義在于可以減少TCP三次握手的開銷,即減少了TCP連接的重復(fù)建立和斷開所造成的額外開銷,使 HTTP 請求和響應(yīng)能夠更早地結(jié)束,這樣 Web 頁面的顯示速度也就相應(yīng)提高了。然而在 HTTP/1.1 協(xié)議中客戶端在同一時間,針對同一域名下的請求有一定數(shù)量限制。超過限制數(shù)目的請求會被阻塞。HTTP/2 通過讓所有數(shù)據(jù)流共用同一個連接,可以更有效地使用 TCP 連接,讓高帶寬也能真正的服務(wù)于 HTTP 的性能提升。所以說HTTP/2時未來發(fā)展的趨勢。

四、重定向

URL 重定向,也稱為 URL 轉(zhuǎn)發(fā),是一種當(dāng)實際資源,如單個頁面、表單或者整個 Web 應(yīng)用被遷移到新的 URL 下的時候,保持(原有)鏈接可用的技術(shù)。

進(jìn)行URL重定向時,服務(wù)器只在響應(yīng)信息的HTTP頭信息中設(shè)置了HTTP狀態(tài)碼和Location頭信息。
當(dāng)狀態(tài)碼為301或302時(301-永久重定向、302-臨時重定向),表示資源位置發(fā)生了改變,需要進(jìn)行重定向。
Location頭信息表示了資源的改變的位置,即:要跳重定向的URL。

const http = require('http')
http.createServer(function (request, response) {
  console.log('request come', request.url)
  if (request.url === '/') {
    response.writeHead(302, {  // or 301   如果寫成狀態(tài)碼200,頁面將無內(nèi)容
      'Location': '/new'
    })
    response.end("")
  }
  if (request.url === '/new') {
    response.writeHead(200, {
      'Content-Type': 'text/html',
    })
    response.end('<div>this is content</div>')
  }
}).listen(8888)
console.log('server listening on 8888')

當(dāng)我們在地址欄輸入localhost:8888后,直接跳轉(zhuǎn)到localhost:8888/new,并展示出內(nèi)容


image

五、CORS跨域請求資源

1.跨域資源共享CORS簡介

CORS是一個W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務(wù)器,發(fā)出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
CORS需要瀏覽器和服務(wù)器同時支持。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。

整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對于開發(fā)者來說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。

因此,實現(xiàn)CORS通信的關(guān)鍵是服務(wù)器。只要服務(wù)器實現(xiàn)了CORS接口,就可以跨源通信。

2.如何實現(xiàn)

瀏覽器將CORS請求分成兩類:簡單請求和非簡單請求。

接下來我們舉一個簡單請求的例子,來說明CORS如何實現(xiàn)跨域請求:

http://127.0.0.1:8888http://127.0.0.1:8887請求資源

//server.js文件  http://127.0.0.1:8888           node server.js 啟動服務(wù)器
const http = require('http')
const fs = require('fs')

http.createServer(function (request, response) {
  console.log('request come', request.url)
  const html = fs.readFileSync('test.html', 'utf8')
  response.writeHead(200, {
    'Content-Type': 'text/html'
  })
  response.end(html)
}).listen(8888)

console.log('server listening on 8888')
//test.html 文件  向http://127.0.0.1:8887請求數(shù)據(jù)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>  
</body>
<script>
  var xhr = new XMLHttpRequest()
  xhr.open('GET', 'http://127.0.0.1:8887/')
  xhr.send()
</script>
</html>
//server.js文件  http://127.0.0.1:8887                node server2.js 啟動服務(wù)器
const http = require('http')
http.createServer(function (request, response) {
  console.log('request come', request.url)
  response.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'//表示接受8888端口的請求
  })
  response.end('123')
}).listen(8887)
console.log('server listening on 8887')

最后得到如下結(jié)果:

image

六、Content Security Policy(CSP)

1.CSP簡介

跨域腳本攻擊 XSS 是最常見、危害最大的網(wǎng)頁安全漏洞。為了防止它們,要采取很多編程措施,非常麻煩。很多人提出,能不能根本上解決問題,瀏覽器自動禁止外部注入惡意腳本?
CSP 的實質(zhì)就是白名單制度,開發(fā)者明確告訴客戶端,哪些外部資源可以加載和執(zhí)行,等同于提供白名單。它的實現(xiàn)和執(zhí)行全部由瀏覽器完成,開發(fā)者只需提供配置。

CSP 大大增強(qiáng)了網(wǎng)頁的安全性。攻擊者即使發(fā)現(xiàn)了漏洞,也沒法注入腳本,除非還控制了一臺列入了白名單的可信主機(jī)。

2.如何實現(xiàn)

如何啟用CSP,可以通過 HTTP 頭信息的Content-Security-Policy的字段

image

接下來我們看一個例子:如何限制加載內(nèi)嵌的script

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div>This is content</div>
  <script>
    console.log('inline js')//禁止這段script代碼執(zhí)行
  </script>
</body>
</html>
const http = require('http')
const fs = require('fs')
http.createServer(function (request, response) {
  console.log('request come', request.url)
    const html = fs.readFileSync('test.html', 'utf8')
    response.writeHead(200, {
      'Content-Type': 'text/html',
      'Content-Security-Policy': "default-src http:https:"http://限制所有的外部資源,都只能從http/https加載。
    })
    response.end(html)
}).listen(8888)
console.log('server listening on 8888')

最后控制臺提示如下錯誤:


image

如果覺得文章對你有些許幫助,歡迎在我的GitHub博客點贊和關(guān)注,感激不盡!

參考文章

《圖解HTTP》[日] 上野宣 著

《計算機(jī)網(wǎng)絡(luò)》謝希仁著

Content Security Policy 入門教程

跨域資源共享 CORS 詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容