每天學點node系列-http
任何可以使用JavaScript來編寫的應用,最終會由JavaScript編寫。--Atwood's Law
http模組概覽
http模組主要用於建立http server服務,並且
- 支援更多特性
- 不緩衝請求和響應
- 能夠流式傳輸資料
藉助http模組,可以幾行程式碼就搞定一個超迷你的web server:
var http=require("http") http.createServer(function(req, res){ res.writeHead(200,{ "content-type":"text/plain" }) res.write("hello nodejs") res.end() }).listen(3000)
http伺服器
像上面一樣使用的createServer方法返回了一個http.Server物件,這其實是一個建立http服務的捷徑,如果我們用以下程式碼來實現的話,也將一樣可行
var http = require("http") var server = new http.Server() server.on("request", function(req, res){ res.writeHead(200, { "content-type":"text/plain" }) res.write("hello nodejs") res.end() }) server.listen(3000)
以上程式碼是通過直接建立一個http.Server物件,然後為其新增request事件監聽,其實也就說createServer方法其實本質上也是為http.Server物件添加了一個request事件監聽。
http.Server的事件
http.Server繼承自 net.Server,http.Server提供的事件如下:
- request:當客戶端請求到來時,該事件被觸發,提供兩個引數req和res,表示請求和響應資訊,是最常用的事件
- connection:當TCP連線建立時,該事件被觸發,提供一個引數socket,是net.Socket的例項
- close:當伺服器關閉時,觸發事件(注意不是在使用者斷開連線時)
正如上面我們所看到的request事件是最常用的,而引數req和res分別是http.IncomingMessage和http.ServerResponse的例項,那麼我們來看看這兩個類
http.IncomingMessage
在server端:獲取請求傳送方的資訊,比如請求方法、路徑、傳遞的資料等。
在client端:獲取 server 端傳送過來的資訊,比如請求方法、路徑、傳遞的資料等。
http.IncomingMessage例項 有三個屬性需要注意:method、statusCode、statusMessage。
- method:只在 server 端的例項有(也就是 serverReq.method)
- statusCode/statusMessage:只在 client 端 的例項有(也就是 clientRes.method)
並且其提供了3個事件,如下
- data:當請求體資料到來時,該事件被觸發,該事件提供一個引數chunk,表示接受的資料,如果該事件沒有被監聽,則請求體會被拋棄,該事件可能會被呼叫多次(這與nodejs是非同步的有關係)
- end:當請求體資料傳輸完畢時,該事件會被觸發,此後不會再有資料
- close:使用者當前請求結束時,該事件被觸發,不同於end,如果使用者強制終止了傳輸,也是用close
http.ServerResponse
http.ServerResponse 的作用很明確,服務端通過http.ServerResponse 例項,來個請求方傳送資料。包括髮送響應表頭,傳送響應主體等。它決定了使用者最終看到的內容,一般也由http.Server的request事件傳送,並作為第二個引數傳遞,它有三個重要的成員函式,用於返回響應頭、響應內容以及結束請求
- res.writeHead(statusCode,[heasers]):向請求的客戶端傳送響應頭,該函式在一個請求中最多呼叫一次,如果不呼叫,則會自動生成一個響應頭
- res.write(data,[encoding]):想請求的客戶端傳送相應內容,data是一個buffer或者字串,如果data是字串,則需要制定編碼方式,預設為utf-8,在res.end呼叫之前可以多次呼叫
- res.end([data],[encoding]):結束響應,告知客戶端所有傳送已經結束,當所有要返回的內容傳送完畢時,該函式必需被呼叫一次,兩個可選引數與res.write()相同。如果不呼叫這個函式,客戶端將用於處於等待狀態。
http客戶端
http模組提供了兩個函式http.request和http.get,功能是作為客戶端向http伺服器發起請求。
var http = require('http')
// http server
var server = http.createServer(function(req, res){
var url = req.url
res.end( '您訪問的地址是:' + url )
})
server.listen(3000)
// http client
var client = http.get('http://127.0.0.1:3000', function(res){
res.setEncoding("utf-8")
res.on("data",function(chunk){
console.log(chunk.toString())
})
console.log(res.statusCode);
})
client.on("error",function(err){
console.log(err.message)
})
client.end()
http.ClientRequest
此物件由 http.request()
內部建立並返回。 它表示正在進行的請求,且其請求頭已進入佇列。 請求頭仍然可以使用 setHeader(name, value)
、getHeader(name)
或 removeHeader(name)
改變。 實際的請求頭將與第一個資料塊一起傳送,或者當呼叫 request.end()
時傳送。
要獲得響應,則為請求物件新增 'response'
事件監聽器。 當接收到響應頭時,將、則會從請求物件觸發 'response' 事件。 'response' 事件執行時有一個引數,該引數是 http.IncomingMessage 的例項。
在 'response'
事件期間,可以新增監聽器到響應物件,比如監聽 'data'
事件。
如果沒有新增 'response' 事件處理函式,則響應將被完全丟棄。 如果添加了 'response' 事件處理函式,則必須消費完響應物件中的資料,每當有 'readable' 事件時呼叫 response.read()、或新增 'data' 事件處理函式、或通過呼叫 .resume() 方法。 在消費完資料之前,不會觸發 'end' 事件。 此外,在讀取資料之前,它將佔用記憶體,最終可能導致程序記憶體不足的錯誤。
Node.js 不檢查 Content-Length 和已傳輸的主體的長度是否相等。
請求繼承自流,且額外實現以下內容:
- 'abort': 當請求被客戶端中止時觸發。 此事件僅在第一次呼叫 abort() 時觸發。
- 'timeout':當底層套接字因不活動而超時時觸發。 這隻會通知套接字已空閒。 必須手動中止請求。
- ...