本文摘錄自《Nodejs學習筆記》,更多章節及更新,請訪問 github主頁地址。歡迎加群交流,群號 197339705。
http模塊概覽
大多數nodejs開發者都是沖着開發web server的目的選擇了nodejs。正如官網所展示的,借助http模塊,可以幾行代碼就搞定一個超迷你的web server。
在nodejs中,http
可以說是最核心的模塊,同時也是比較復雜的一個模塊。上手很簡單,但一旦深入學習,不少初學者就會覺得頭疼,不知從何入手。
本文先從一個簡單的例子出發,引出http
模塊最核心的四個實例。看完本文,應該就能夠對http模塊有個整體的認識。
一個簡單的例子
在下面的例子中,我們創建了1個web服務器、1個http客戶端
- 服務器server:接收來自客戶端的請求,並將客戶端請求的地址返回給客戶端。
- 客戶端client:向服務器發起請求,並將服務器返回的內容打印到控制台。
代碼如下所示,只有幾行,但包含了不少信息量。下一小節會進行簡單介紹。
var http = require('http');
// http server 例子
var server = http.createServer(function(serverReq, serverRes){
var url = serverReq.url;
serverRes.end( '您訪問的地址是:' + url );
});
server.listen(3000);
// http client 例子
var client = http.get('http://127.0.0.1:3000', function(clientRes){
clientRes.pipe(process.stdout);
});
例子解釋
在上面這個簡單的例子里,涉及了4個實例。大部分時候,serverReq、serverRes 才是主角。
- server:http.Server實例,用來提供服務,處理客戶端的請求。
- client:http.ClientReques實例,用來向服務端發起請求。
- serverReq/clientRes:其實都是 http.IncomingMessage實。serverReq 用來獲取客戶端請求的相關信息,如request header;而clientRes用來獲取服務端返回的相關信息,比如response header。
- serverRes:http.ServerResponse實例
關於http.IncomingMessage、http.ServerResponse
先講下 http.ServerResponse 實例。作用很明確,服務端通過http.ServerResponse 實例,來個請求方發送數據。包括發送響應表頭,發送響應主體等。
接下來是 http.IncomingMessage 實例,由於在 server、client 都出現了,初學者難免有點迷茫。它的作用是
在server端:獲取請求發送方的信息,比如請求方法、路徑、傳遞的數據等。
在client端:獲取 server 端發送過來的信息,比如請求方法、路徑、傳遞的數據等。
http.IncomingMessage實例 有三個屬性需要注意:method、statusCode、statusMessage。
- method:只在 server 端的實例有(也就是 serverReq.method)
- statusCode/statusMessage:只在 client 端 的實例有(也就是 clientRes.method)
關於繼承與擴展
http.Server
- http.Server 繼承了 net.Server (於是順帶需要學一下 net.Server 的API、屬性、相關事件)
- net.createServer(fn),回調中的
socket
是個雙工的stream接口,也就是說,讀取發送方信息、向發送方發送信息都靠他。
備注:socket的客戶端、服務端是相對的概念,所以其實 net.Server 內部也是用了 net.Socket(不負責任猜想)
// 參考:https://cnodejs.org/topic/4fb1c1fd1975fe1e1310490b
var net = require('net');
var PORT = 8989;
var HOST = '127.0.0.1';
var server = net.createServer(function(socket){
console.log('Connected: ' + socket.remoteAddress + ':' + socket.remotePort);
socket.on('data', function(data){
console.log('DATA ' + socket.remoteAddress + ': ' + data);
console.log('Data is: ' + data);
socket.write('Data from you is "' + data + '"');
});
socket.on('close', function(){
console.log('CLOSED: ' +
socket.remoteAddress + ' ' + socket.remotePort);
});
});
server.listen(PORT, HOST);
console.log(server instanceof net.Server); // true
http.ClientRequest
http.ClientRequest 內部創建了一個socket來發起請求,代碼如下。
當你調用 http.request(options) 時,內部是這樣的
self.onSocket(net.createConnection(options));
http.ServerResponse
- 實現了 Writable Stream interface,內部也是通過socket來發送信息。
http.IncomingMessage
- 實現了 Readable Stream interface,參考這里
- req.socket --> 獲得跟這次連接相關的socket