一、http服務器
我們知道傳統的HTTP服務器是由Aphche、Nginx、IIS之類的軟件來搭建的,但是Nodejs並不需要,Nodejs提供了http模塊,自身就可以用來構建服務器。例如,下面的代碼就是使用Nodejs搭建了一個簡易的服務器:
/** *main.js *在終端輸入node main.js,打開瀏覽器在地址欄輸入localhost:3000 *瀏覽器顯示Hello Nodejs */ //獲取http模塊 var http = require("http"); //獲取http.Server對象 var server = new http.Server(); //創建服務器,並監聽3000端口 server.on("request",function(req,res) { res.writeHead(200,{ "content-type":"text/plain" }); res.write("Hello Nodejs"); res.end(); }).listen(3000);
http模塊中封裝了一個HTTP服務器和一個簡易的HTTP客戶端:使用http.Server類創建一個基於事件的HTTP服務器,而使用http.request()和http.get()方法則可以作為HTTP客戶端向服務器發起請求。
上面的示例代碼創建了一個http.Server對象,然后為其添加request事件監聽,這個事件會在每次接收到請求時觸發。text/plain的意思是將文件設置為純文本格式,瀏覽器在獲取到這種文件時並不會對其進行處理,如果將content-type設置為text/html,瀏覽器在獲取到這種文件時會自動調用HTML的解析器對文件進行相應的處理。另外,也可以使用createServer()方法簡化這一過程:
var http = require("http"); //createServer()方法創建的http.Server對象默認添加了一個request事件監聽 http.createServer(function(req,res) { res.writeHead(200,{ "content-type":"text/plain" }); res.write("Hello Nodejs"); res.end(); }).listen(3000);
上面說到了http.Server類的事件,http.Server類最常用的事件是"request"事件。在"request"事件中,傳入回調函數的參數req和res分別是http.IncomingMessage類(它實現了可讀流的接口)和http.ServerResponse類(它實現了可寫流的接口)的實例。
1、IncomingMessage對象包含了從客戶端發來的http請求信息,它可以用來訪問響應狀態、消息頭、以及數據等,例如:
var http = require("http"); http.createServer(function(req,res) { console.log(req.httpVersion);//http協議版本,可能的值有"1.1"或"1.0" console.log(req.method);//請求的方法,例如"GET"、"POST"等 console.log(req.statusCode);//http響應狀態碼 console.log(req.statusMessage);//http響應狀態消息 console.log(req.headers);//請求頭或響應頭的對象 console.log(req.url);//發送http請求的客戶端的url }).listen(3000);
IncomingMessage對象包含的事件、方法以及屬性參考手冊:http://nodejs.cn/api/http.html#http_class_http_incomingmessage
2、http.ServerResponse類是返回給客戶端的信息,它有三個重要的方法,用於返回響應頭、響應內容以及結束請求:
writeHead(statusCode[, statusMessage][, headers]):向請求的客戶端發送響應頭,該函數在一個請求中最多調用一次,如果不調用,則會自動生成一個響應頭。statusCode是一個三位數的http狀態碼,如“200”表示請求成功、“404”表示請求的資源不存在;statusMessage是一個字符串,用來描述狀態;headers是一個對象,即響應頭。
write(chunk[, encoding][, callback]):向請求的客戶端發送響應體,在end()方法被調用前可以多次調用。chunk是一個buffer或者字符串,如果chunk是字符串,則在第二個參數需要指定編碼方式,默認為utf-8。
end([chunk][, encoding][, callback]):該方法會通知服務器,所有響應頭和響應主體都已被發送,每次響應都必須調用end()方法來結束。
ServerResponse對象包含的事件、方法以及屬性參考手冊:http://nodejs.cn/api/http.html#http_class_http_serverresponse
http.Server類的事件參考手冊:http://nodejs.cn/api/http.html#http_class_http_server
二、http客戶端
http模塊提供了http.request()和http.get()兩個方法,功能是作為客戶端向http服務器發起請求。
1、關於http.request(options[, callback])
options是一個對象,包含了請求的相關參數:http://nodejs.cn/api/http.html#http_http_request_options_callback
可選參數callback會作為單次監聽器被添加到”response“事件,即當請求的響應被接收到時就會調用該回調函數。它在被執行時帶有一個參數res,該參數是一個 http.IncomingMessage類的實例
返回值是一個http.ClientRequest 類的實例,它表示着一個正在處理的請求
例如:
/** *c.js *HTTP客戶端,發送HTTP請求 *控制台輸出返回的響應內容 */ var http = require("http"); var options = { host: "localhost", port: 3000 } var req = http.request(options,function(res) { res.on("data",function(chunk) { console.log(chunk.toString("utf-8")); }); res.on("end",function() { console.log("----請求結束!----"); }); }); req.on("error",function(err) { console.log(err.message); }); req.end();
/** *s.js *HTTP服務器 */ var http = require("http"); http.createServer(function(req,res) { res.writeHead(200,{ "content-type":"text/plain" }); res.write("Hello Nodejs"); res.end(); }).listen(3000);
如果請求過程中遇到任何錯誤,則在返回的請求對象中會觸發"error"事件;
使用http.request()必須總是調用req.end()來表明請求的結束,即使沒有數據被寫入請求體;
2、關於http.get(options[,callback])方法
http.get()方法是http.request()方法的簡化版,主要區別是http.get()自動將請求方法設為了"GET",同時不需要手動調用req.end()。
三、總結
Nodejs的http模塊常用的類和方法:
1、http.Server 類:用於創建HTTP服務器,使用時需要先實例化;
2、http.ClientRequest 類:該對象在 http.request() 內部被創建並返回。它表示着一個正在處理的請求;
3、http.IncomingMessage 類:IncomingMessage對象由 http.Server 或 http.ClientRequest 創建,並作為第一個參數分別傳遞給 'request' 和 'response' 事件。 它可以用來訪問響應狀態、消息頭、以及數據。它實現了可讀流接口;
4、http.ServerResponse 類:ServerResponse對象由http.Server創建,並作為第二個參數傳遞給 'request' 事件。它實現了可寫流接口;
5、http.createServer( [callback] )方法:返回一個http.Server對象,callback會被自動添加到 'request' 事件中;
6、http.request( options[, callback] )方法:作為http客戶端,向服務器發送請求,可選參數callback會被自動添加到 'response'事件中;
7、http.get( options[, callback] )方法:http.request()方法的簡化版,主要區別是http.get()自動將請求方法設為了"GET",同時不需要手動調用req.end();