1. 程式人生 > >NodeJs內建模組之HTTP模組

NodeJs內建模組之HTTP模組

一、HTTP協議與流

1.客戶端上的 HTTP 請求

ClientRequest的例項 ——可寫流

一般由http.request()方法建立返回

http.request(options[, callback])

引數說明:
options :可以是一個物件、或字串、或 URL 物件。 如果 options 是一個字串,它會被自動使用 url.parse() 解析。 如果它是一個 URL 物件, 它會被預設轉換成一個 options 物件。
callback :可選的。
callback 引數會作為單次監聽器被新增到 ‘response’ 事件。
1)'response'事件


當請求的響應被接收到時觸發。 該事件只觸發一次
繫結的回撥函式的第一個引數是一個<http.IncomingMessage>
2)write
傳送請求主體的一個數據塊。

request.write(chunk[, encoding][, callback])
    chunk
    encoding
    callback

通過多次呼叫該方法,一個請求主體可被髮送到一個伺服器,在這種情況下,

3)end
結束髮送請求。 如果部分請求主體還未被髮送,則會重新整理它們到流中。

    request.end([data[, encoding]][, callback])
data encoding callback

如果指定了 data,則相當於呼叫 request.write(data, encoding) 之後再呼叫 request.end(callback)。
如果指定了 callback,則當請求流結束時會被呼叫

4)getHeader

讀出請求頭,注意:引數name是大小寫敏感的

    request.getHeader(name)

5)setHeader
為 headers 物件設定一個單一的 header 值。

request.setHeader(name, value
)

如果該 header 已經存在了,則將會被替換。這裡使用一個字串陣列來設定有相同名稱的多個 headers。
6) removeHeader

2、伺服器上的 HTTP 響應
ServerResponse的例項 ——可寫流
request事件回撥的第二個引數。
以下方法事件都從屬於ServerResponse。
1) 'close' 事件
當底層連線在 response.end() 被呼叫時觸發。
2) 'finish' 事件
當響應已被髮送時觸發。 更具體地說,當響應頭和響應主體的最後一部分已被交給作業系統通過網路進行傳輸時,觸發該事件。 這並不意味著客戶端已接收到任何東西。
該事件觸發後,響應物件上不再觸發其他事件。
3) write

    response.write(chunk[, encoding][, callback])

該方法會發送一塊響應主體。 它可被多次呼叫,以便提供連續的響應主體片段

chunk 可以是一個字串或一個 buffer
encoding 代表編碼預設為 'utf8'
callback 代表回撥 在資料塊被重新整理時會呼叫

4) end

response.end([data][, encoding][, callback])

該方法會通知伺服器,所有響應頭和響應主體都已被髮送,即伺服器將其視為已完成。 每次響應都必須呼叫 response.end() 方法。
如果指定了 data,則相當於呼叫 response.write(data, encoding) 之後再呼叫 response.end(callback)。
如果指定了 callback,則當響應流結束時被呼叫

5) getHeader

    response.getHeader(name)

讀取一個已入佇列但尚未傳送到客戶端的響應頭。
注意,名稱不區分大小寫
6)setHeader
為一個隱式的響應頭設定值。 如果該響應頭已存在,則值會被覆蓋。 如果要傳送多個名稱相同的響應頭,則使用字串陣列

    response.setHeader(name, value)

7)writeHead
response.setHeader() 設定的響應頭會與 response.writeHead() 設定的響應頭合併,且 response.writeHead() 的優先。

response.writeHead(statusCode[, statusMessage][, headers])
                    statusCode    三位數的 HTTP 狀態碼
                    statusMessage  可選的狀態描述
                    headers         報文物件
                                    {
                                        'Content-Length': Buffer.byteLength(body),
                                        'Content-Type': 'text/plain'
                                     }

8) hasHeader
9)removeHeader

3、http.IncomingMessage 可讀流
IncomingMessage 物件由 http.Server 或 http.ClientRequest 建立,並作為第一個引數分別遞給 ‘request’ 和 ‘response’ 事件。 它可以用來訪問響應狀態、訊息頭、以及資料。
1)headers
請求頭或響應頭的物件
2) httpVersion
在伺服器請求中,該屬性返回客戶端傳送的 HTTP 版本。 在客戶端響應中,該屬性返回連線到的伺服器的 HTTP 版本。 可能的值有 ‘1.1’ 或 ‘1.0’。
3)method
返回一個字串,表示請求的方法。 該屬性只讀(僅在 http.Server 返回的請求中有效).
4)statusCode
返回一個三位數的 HTTP 響應狀態碼
(僅在 http.ClientRequest 返回的響應中有效。)
5)statusMessage
返回 HTTP 響應狀態訊息(原因描述)。 如 OK 或 Internal Server Error。
(僅在 http.ClientRequest 返回的響應中有效。)
6)url
返回請求的 URL 字串(僅在 http.Server 返回的請求中有效)

二、使用node搭建最簡單的http服務

1、http方法
request:返回一個ClientRequest例項

http.request(options[, callback])

createServer: 建立一個server例項

    http.createServer([options][, requestListener])

引數說明:
options一般不傳
返回一個新的 http.Server例項。
requestListener是一個自動新增到’request’事件的方法。

2、http.Server

'request'事件:每次接收到一個請求時觸發事件回撥函式,
有兩個引數:

    message IncomingMessage
    response ServerResponse

listen:開啟服務

        server.listen([port[, host]][, callback])

引數說明:
port:埠 預設系統分配無用埠
host:主機名 預設是迴路
callback:回撥

3、 使用步驟

1) 引入http模組

const http = require("http");

2)指定主機與埠

const host = "127.0.0.1";
const port = 8000;

3)建立一個服務

http.createServer([requestListener])

引數說明:
requestListener : ‘request’ 回撥函式
返回值:一個新的http.Server

4)為服務繫結請求的監聽

server.on(“request”,fn)

fn在每次接收到一個請求時觸發,它有兩個引數

    request:<http.IncomingMessage>
    response: <http.ServerResponse>

ServerResponse實現了可寫流介面

5)開啟這個服務
server.listen([port[, host]][, callback])
port:埠
host:主機
callback:服務啟動的回撥

server.listen(port,host,()=>{
    console.log("服務啟動了")
});

4、程式碼例項:

const http = require("http")
const host = "127.0.0.1";
const port = 8080
const server = http.createServer();
server.on("request", (requstMsg, respone) => {
    console.log("請求來了",requstMsg.headers)
    //簡單請求
    respone.writeHead(200, "OK", {"Content-Type": "text/html; charset=utf-8"});
    respone.end("最簡單的http服務");
})
server.listen(port, host, () => {
    console.log("服務啟動了")
})

測試結果:
這裡寫圖片描述

三、客戶端和服務端資料互動

在NodeJs中,客戶端和服務端都是通過監聽data事件,進行資料互動。

requstMsg.on("data",(data)=>{
        console.log("data:",data.toString());
    })

1、 伺服器上的 HTTP 響應
server.js

const http = require("http")
const host = "127.0.0.1";
const port = 8080
const server = http.createServer();
const fs = require("fs")
const readStream = fs.createReadStream("./html/demo.html")
server.on("request", (requstMsg, respone) => {
    console.log("請求來了",requstMsg.headers)
    // console.log(requstMsg.url)
    requstMsg.on("data",(data)=>{
        console.log("data:",data.toString());
    })

    respone.setHeader("Content-Type","application/x-javascript")
    readStream.pipe(respone)

})
server.listen(port, host, () => {
    console.log("服務啟動了")
})

2、 客戶端上的 HTTP 請求
client.js

const http = require("http")
const str = "username=damu&userage=18";
const buf = Buffer.from(str);
const request = http.request("http://127.0.0.1:8080",(responeMsg)=>{
    console.log(responeMsg.statusCode)
    console.log(responeMsg.statusMessage)
    responeMsg.on("data",(data)=>{
        console.log("data:",data.toString());
    })
});
request.method="POST";
request.setHeader("Content-Type","application/x-www-form-urlencoded");
request.setHeader("Content-Length",buf.length);
request.write(buf)
request.end()

3、測試:
首先執行server,js,
這裡寫圖片描述
執行client.js
這裡寫圖片描述
此時sever端
這裡寫圖片描述

四、URL——處理http協議請求報文中的URI

1、url模組
1) url.protocol <string>
獲取及設定URL的協議(protocol)部分
2) url.host <string>
獲取及設定URL的主機(host)部分
3) url.hostname <string>
獲取及設定URL的主機名(hostname)部分。 url.host和url.hostname之間的區別是url.hostname不 包含埠
4) url.port <string>
獲取及設定URL的埠(port)部分。
5) url.pathname<string>
獲取及設定URL的路徑(path)部分
6) url.search<string>
獲取及設定URL的序列化查詢字串
7) url.query<string>
獲取及設定URL的序列化查詢物件
8) url.hash <string>
獲取及設定URL的分段(hash)部分
9) url.href <string>
獲取及設定序列化的URL
10) url.parse()

    url.parse(urlString,[ parseQueryString])
    urlString <string> 要解析的 URL 字串。
    parseQueryString <boolean> 如果為 true,則 query 屬性總會通過 querystring 模組的 parse() 方法生成一個物件。 如果為 false,則返回的 URL 物件上的 query 屬性會是一個未解析、未解碼的字串。 預設為 false

11) url.format(urlObject)
url.parse的逆運用
12) url.resolve(from, to)
url.resolve() 方法會以一種 Web 瀏覽器解析超連結的方式把一個目標 URL 解析成相對於一個基礎 URL。

url.resolve(from, to)
from <string> 解析時相對的基本 URLto <string> 要解析的超連結 URL

程式碼例項:

const url = require('url');
url.resolve('/one/two/three', 'four');         // '/one/two/four'
url.resolve('http://example.com/', '/one');    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'

2、querystring模組
1)querystring.stringify
序列化查詢字串

querystring.stringify(obj[, sep[, eq]])
                    obj <Object> 要序列化成 URL 查詢字串的物件。
                    sep <string> 用於界定查詢字串中的鍵值對的子字串。預設為 '&'。
                    eq <string> 用於界定查詢字串中的鍵與值的子字串。預設為 '='

2) querystring.parse
反序列化

querystring.parse(str[, sep[, eq]])
                str <string> 要解析的 URL 查詢字串。
                sep <string> 用於界定查詢字串中的鍵值對的子字串。預設為 '&'。
                eq <string> 用於界定查詢字串中的鍵與值的子字串。預設為 '='