http資料協商

littlebirdflying發表於2018-09-22

資料協商的概念

客戶端傳送請求給服務端,客戶端會宣告請求希望拿到的資料的格式和限制,服務端會根據請求頭資訊,來決定返回的資料。

分類

請求 Accept

返回 Content

Accept

Accept 宣告想要資料的型別

Accept-Encoding 資料以哪種編碼方式傳輸,限制服務端如何進行資料壓縮。

Accept-Language 展示語言

User-Agent 瀏覽器相關資訊,移動端、客戶端、pc端的瀏覽器 User-Agent 不同。

Content

服務端返回

Content-Type 對應 Accept,從 Accept 中選擇資料型別返回

Content-Encoding 對應 Accept-Encoding,宣告服務端資料壓縮的方式

Content-Language 對應 Accept-Language,是否根據請求返回語言

瀏覽器請求 html 時的頭資訊

啟動伺服器 node server.js,localhost:8888 埠訪問,test.html先設為空。

// server.js
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')
  response.writeHead(200, {
    'Content-Type': 'text/html',
    // 'X-Content-Options': 'nosniff'
    // 'Content-Encoding': 'gzip'
  })
  // response.end(zlib.gzipSync(html))
  response.end(html)
}).listen(8888)

console.log('server listening on 8888')
複製程式碼

檢視 network 的 localhost 檔案的請求資訊,瀏覽器會自動加上這些頭資訊。

Response Headers

Connection: keep-alive
Content-Type: text/html
Date: Fri, 21 Sep 2018 02:29:16 GMT
Transfer-Encoding: chunked

Request Headers

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Cookie: 
Host: localhost:8888
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
複製程式碼

請求頭

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

瀏覽器可以接收這些格式的資料,可以進行設定。

Accept-Encoding: gzip, deflate, br

資料編碼方式,gzip 使用最多;br 使用比較少,但壓縮比高。

Accept-Language: zh-CN,zh;q=0.9

瀏覽器會判斷本系統的語言,自動加上。q 代表權重,數值越大權重越大,優先順序越高。

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36

Mozilla/5.0 瀏覽器最早是網景公司出的,當時預設頭是 Mozilla/5.0,很多老的 http 伺服器只支援這個頭,所以加上相容老的 web 伺服器。

AppleWebKit/537.36 瀏覽器核心 ,chrome 和 safari 等現代瀏覽器大部分使用 webkit 核心,webkit 核心是蘋果公司開發的

KHTML 渲染引擎版本,類似於 Gecko,火狐瀏覽器渲染引擎

Chrome/68.0.3440.106 chrome 版本號

Safari/537.36 因為使用了 webkit 核心,所以會加上

服務端根據資料協商的資訊進行判斷,返回客戶端想要的資訊。

在傳送 ajax 請求時可以自定義設定 accept 相關資訊

content type 相關

mime type

Accept-Encoding

資料壓縮

請求檔案大小 933B,使用 gzip 壓縮後是 609B

// server.js
const http = require('http')
const fs = require('fs')
const zlib = require('zlib') // 引入包

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',
    // 'X-Content-Options': 'nosniff'
    'Content-Encoding': 'gzip'
  })
  response.end(zlib.gzipSync(html)) // 壓縮
}).listen(8888)

console.log('server listening on 8888')
複製程式碼

請求檔案響應頭

Response Headers

Connection: keep-alive
Content-Encoding: gzip // 返回的壓縮演算法方式
Content-Type: text/html
Date: Fri, 21 Sep 2018 02:58:54 GMT
Transfer-Encoding: chunked
複製程式碼

Content-type

用來協商客戶端和服務端的資料格式和宣告

傳送請求時,會有不同的請求內容,根據內容不同設定不同的 content-type

chorme瀏覽器設定,勾選 Preserve log,當頁面跳轉後,也會把之前的請求列印出來

傳送表單資料

<body>
  <form action="/form" method="POST" id="form" enctype="application/x-www-form-urlencoded">
    <input type="text" name="name">
    <input type="password" name="password">
    <input type="submit">
  </form>
</body>
</html>
複製程式碼
Request Headers
Content-Type: application/x-www-form-urlencoded // content-type 就是 form表單中設定的

Form Data
name=sf&password=sfs
複製程式碼

服務端根據 content-type 是 x-www-form-urlencoded來對body 中的資料進行轉化即可。

如果表單資料中有檔案

<body>
  <form action="/form" method="POST" id="form" enctype="multipart/form-data">
    <input type="text" name="name">
    <input type="password" name="password">
    <input type="file" name="file">
    <input type="submit">
  </form>
  <script>
    var form = document.getElementById('form')
    form.addEventListener('submit', function (e) {
      e.preventDefault()
      var formData = new FormData(form)
      fetch('/form', {
        method: 'POST',
        body: formData
      })
    })
  </script>
</body>
複製程式碼

代表請求是有多個部分的,有時通過表單上傳檔案時,必須要把檔案部分單獨拆分出來,檔案不能作為字串進行傳輸的,要作為二進位制的資料進行傳輸;使用 x-www-form-urlencoded 這種拼接字串的方式 是不對的

Request Headers
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary39Ug3FSPIBvDYZd6

Request Payload
------WebKitFormBoundary39Ug3FSPIBvDYZd6
Content-Disposition: form-data; name="name"

sdfs
------WebKitFormBoundary39Ug3FSPIBvDYZd6
Content-Disposition: form-data; name="password"

sdfs
------WebKitFormBoundary39Ug3FSPIBvDYZd6
Content-Disposition: form-data; name="file"; filename="1536973449110.png"
Content-Type: image/png


------WebKitFormBoundary39Ug3FSPIBvDYZd6--
複製程式碼

boundary=----WebKitFormBoundarybwAbNlPF2bBcTLuA用來分割表單提交資料的各個部分

服務端拿到表單資料後,根據這個分割字串,進行資料分割。

相關文章