簡單瞭解 node http(一)

簡單瞭解 node http 模塊javascript

文章記錄了對http 模塊的簡單使用與理解。html

  • http 服務端
  • http 客戶端
  • 總結

1. http 服務端

先寫個小例子java

服務端:node

let http = require('http')
let server = http.createServer((req, res) => {
  let buf = []
  req.on('data', data => {
    buf.push(data)
  })
  req.on('end', () => {
    let str = Buffer.concat(buf).toString()
    res.end(str)
  })
})

server.listen(8080, () => {
  console.log('server start')
})複製代碼
大概代碼執行流程:
http.createServer() 返回新建的 http.Server 實例。http.Server 繼承自net.Server。requestListener 是一個自動添加到到 'request' 事件的函數。
'request' 事件 每次請求的時候都會觸發。http服務是以request爲單位進行服務的。
http.IncomingMessage 對象,它可用於訪問本次,請求的請求方法、消息頭、以及數據(圖中將,請求頭與數據拆分開)。
http.ServerResponse 對象,服務端經過http.ServerResponse 實例,來給客戶端(數據請求方)返回本次數據。包括響應頭,響應體(內部經過socket來發送信息)。
http服務端:在TCP模塊套接字 socket 上,將接受的數據解析出請求報文頭和報文主體,將返回的響應報文頭和報文主體組裝成數據發送出去。

1.1 請求:

請求報文由如下組成api

  • 報文首部:請求方法、請求 URI、協議版本、可選的請求首部字段等
  • 空行
  • 報文主體:內容實體構成數據。

node http 模塊 在TCP鏈接的讀操做上,將數據解析成(以空行分割,報文頭和報文體):緩存

報文頭部分:
req.method
req.httpVersionMajor 
req.httpVersionMinor
req.httpVersion
req.upgrade
...
req.headers = {
  Content-Length: 15
  Content-Type: application/x-www-form-urlencoded
... ...
}
// 
報文主體部分:
一個可讀流對象req,能夠繼續報文主體數據的讀取複製代碼

1.2響應

服務端經過http.ServerResponse 實例,來向客戶端(數據請求方)返回本次請求數據。包括響應頭,響應體(內部經過socket來發送信息)。服務器

node http 模塊 在TCP鏈接的寫操做上,將數據寫緩存拼接(以空行拼接,報文頭和報文體)成:
//中間有個空行
"HTTP/1.1 200 OK
Date: Sat, 30 Nov 2019 05:10:05 GMT
Connection: close
Content-Length: 25

"
+ 請求體部分數據或所有數據複製代碼

經過的方法app

// 具體使用參考文檔

// 設置頭部,頭部並無發送 
response.setHeader(name, value)
// 設置頭部,向請求發送響應頭,此方法只能在消息上調用一次,而且必須在調用 response.end() 以前調用。
response.writeHead()
// 若是調用此方法而且還沒有調用 response.writeHead(),則將切換到隱式響應頭模式並刷新隱式響應頭。
// 這會發送一塊響應主體。 能夠屢次調用該方法以提供連續的響應主體片斷。
response.write()
// 此方法向服務器發出信號,代表已發送全部響應頭和主體,該服務器應該視爲此消息已完成。 必須在每一個響應上調用此 response.end() 方法。
response.end() 複製代碼

2. http 客戶端

客戶端向 HTTP服務器發起請求:
let http = require('http')
let options = {
  host: 'localhost',
  port: 8080,
  method: 'POST',
  headers: {
    'content-type': 'application/x-www-form-urlencoded'
  }
}
// 請求並無 發出 req 是個可寫流
let req = http.request(options)

req.on('response', res => {
  console.log(res.headers)
  let buf = []
  res.on('data', data => {
    buf.push(data)
  })
  res.on('end', () => {
    console.log(Buffer.concat(buf).toString())
  })
})
// write 向請求體寫數據
req.write('name=luoxiaobu&title=http')
// 實際的請求頭將會與第一個數據塊一塊兒發送,或者當調用 request.end() 時發送。
req.end()複製代碼

大概代碼執行流程:socket

http.request() 返回 http.ClientRequest 類的實例。http.ClientRequest 內部建立了一個socket來發起請求。函數

ClientRequest 實例是能夠看作可寫流。若是須要使用 POST 請求上傳文件,則寫入到 ClientRequest 對象。

response事件 每次服務器端有數據返回響應時都會觸發。

http.IncomingMessage 對象,它可用於訪問本次服務器端返回的,響應狀態、消息頭、以及數據。

http客戶端:在TCP模塊套接字 socket 上,將求報文頭和報文主體組裝成數據發送出去,將接受的數據解析出響應報文頭和報文主體,。

2.1 請求:

node http 模塊 在TCP鏈接的寫操做上,將數據緩存拼接(以空行拼接,報文頭和報文體)成:
//中間有個空行
"POST / HTTP/1.1
content-type: application/x-www-form-urlencoded
Host: localhost:8080
Connection: close
Transfer-Encoding: chunked

"
+ 請求體部分數據或所有數據複製代碼

經過的方法

// 具體使用參考文檔
const postData = querystring.stringify({
  'msg': '你好世界'
});

const options = {
  hostname: 'localhost:8080',
  path: '/upload',
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': Buffer.byteLength(postData)
  }
};
// 內部會處理 options 解析出頭部
const req = http.request(options, (res) => {
 
});

// 這會發送一塊響應主體。 能夠屢次調用該方法以提供連續的響應主體片斷。
response.write()
// 此方法向服務器發出信號,代表已發送全部響應頭和主體,該服務器應該視爲此消息已完成。 必須在每一個響應上調用此 response.end() 方法。
response.end() 複製代碼

2.2 響應

響應報文圖:

響應報文由如下組成

  • 報文首部:協議版本、狀態碼(表示請求成功或失敗的數字代碼)、用以解釋狀態碼的緣由短語、可選的響應首部字段
  • 空行
  • 報文主體:實體主體構成。

node http 模塊 在TCP鏈接的讀操做上,將數據解析成:

報文頭部分:
res.statusCode = statusCode;
res.statusMessage = statusMessage;
res.httpVersionMajor 
res.httpVersionMinor
res.httpVersion
res.upgrade
...
res.headers = {
  Content-Length: 15
  Content-Type: application/x-www-form-urlencoded
... ...
}
// 
報文主體部分:
一個可讀流對象,能夠繼續報文主體數據的讀取複製代碼

3. 總結

文章記錄了對http 模塊的簡單使用與理解,要深刻理解http 模塊,還需多看文檔,代碼實踐。

文中例子比較粗糙,理解不許確之處,還請教正。


參考資料:<<圖解HTTP>>

nodejs.org/dist/latest…

相關文章
相關標籤/搜索