1. 程式人生 > >Node.js學習筆記5【http伺服器與客戶端】

Node.js學習筆記5【http伺服器與客戶端】

Node.js標準庫提供了http模組,其中封裝了一個高效的HTTP伺服器和一個簡易的HTTP客戶端。http.Server是一個基於事件的http伺服器,它的核心由Node.js下層C++部分實現,而介面由javascript封裝,兼顧了高效能與簡易性。http.request則是一個http客戶端工具,用於向http伺服器發起請求,如內容抓取。

http伺服器

http.Server是http模組中的HTTP伺服器物件,用Node.js做的所有基於HTTP協議系統,如網站、社交應用甚至代理伺服器,都是基於http.Server實現的。它提供了一套封裝級別很低的API,僅僅是流控制和簡單的訊息解析,所有高層功能都要通過它的介面來實現。如:

//app.js

var http =require(‘http’);

http.createServer(function(req,res){

   res.writeHead(200,{‘Content-Type’:’text/html’});

   res.write(‘<h1>Node.js</h1>’);

  res.end(‘<p>Hello World</p>’);

}).listen(3000);

console.log(“HTTPserver is listening at port 3000.”);

1.http.Server的事件

http.Server是一個基於事件的HTTP伺服器,所有的請求都被封裝為獨立的事件,開發者只需要對它的事件編寫響應函式即可實現HTTP伺服器的所有功能。它繼承自EventEmitter,提供了以下幾個事件。

l  request:當客戶端請求到來時,該事件被觸發,提供兩個引數req和res,分別是http.ServerRequest和http.ServerResponse的例項,表示請求和響應資訊。

l  connection:當TCP連線建立時,該事件被觸發,提供一個引數socket,為net.Socket的例項。connection事件的粒度要大於request,因為客戶端在Keep-Alive模式下可能會在同一個連線內傳送多次請求。

l  close:當伺服器關閉時,該事件觸發。注意不是在使用者連線斷開時。

除此之外還有checkContinue、upgrade、clientError事件,通常我們不需要關心,只有實現複雜的HTTP伺服器的時候才會用到。

在這些事件中,最常用的就是request了,因此http提供了一個捷徑:http.createServer([requestListener]),功能是建立一個HTTP伺服器並將requestListener作為request事件的監聽函式,這也是上面例子中的實現方式

下面是顯式方式註冊request事件:

//httpserver.js

var http =require(‘http’);

var server = http.Server();

sever.on(‘request’,function(req,res){

   res.writeHead(200,{‘Content-Type’:’text/html’});

   res.write(‘<h1>Node.js</h1>’);

  res.end(‘<p>Hello World</p>’);

});

sever.listen(3000);

console.log(“HTTPserver is listening at port 3000.”);

2.http.ServerRequest

http.ServerRequest是HTTP請求的資訊,是後端開發者最關注的內容。它一般由http.Server的request事件傳送,作為第一個引數傳遞,通常簡稱為request或req。

屬性有:

名稱

含義

complete

客戶端請求是否已經發送完成

httpVersion

HTTP協議版本,通常是1.0或1.1

method

HTTP請求方法,如GET POST PUT DELETE

url

原始請求路徑

headers

HTTP請求頭

trailers

HTTP請求尾(不常見)

connection

當前http連線套接字,為net.Socket的例項

socket

connection屬性的別名

client

client屬性的別名

HTTP請求一般可以分為兩部分:請求頭和請求體,以上內容由於長度較短都可以在請求頭解析完成後立即讀取,而請求體可能相對較長,需要一定的時間傳輸,因此http.ServerRequest提供了以下3個事件用於控制請求體傳輸。

data:當請求體資料到來時,該事件觸發。該事件提供一個引數chunk,表示接收到的資料,如果該事件沒有被監聽,那麼請求體將被拋棄。該事件可能會被呼叫多次。

end:當請求體資料傳輸完成時,該事件被觸發,此後將不會再有資料到來。

close:使用者當前請求結束時,該事件觸發。不同於end,如果使用者強制終止了傳輸,也還是呼叫close。

3獲取GET請求內容

url模組中的parse函式提的功能:

//httpserverrequestget.js

var http =require(‘http’);

var url = require(‘url’);

var util =require(‘util’);

http.createServer(function(req,res){

   res.writeHead(200,{‘Content-Type’:’text/html’});

  res.end(util.inspect(url.parse(req.url,true)));

}).listen(3000);

parse後返回的物件包含

{

    search:’?name=aaa&key=…’,

    query:{name:’aaa’,key:’’}

    pathname:’問號前的如/user’

    path:’’,

    href:’’

}

4 獲取POST請求內容

HTTP協議1.1版本提供了8種標準的請求方法,其中最常見的就是GET和POST。POST請求的內容全部都在請求體中。http.ServerRequest並沒有一個屬性內容為請求體,原因是等待請求體傳輸可能是一件耗時的工作,譬如上傳檔案。而很多時候我們可能並不需要理會請求的內容,惡意的POST請求會消耗伺服器的資源。所以Node.js預設是不會解析請求體的,當你需要的時候需要手動來做。

//httpserverrequestpost.js

var http =require(‘http’);

var querystring =require(‘querystring’);

var util =require(‘util’);

http.createServer(function(req,res){

   var post = ‘’;

   req.on(‘data’,function(chunk){

         post+=chunk;

   });

   req.on(‘end’,function(){

            post = questring.parse(post);

            res.end(util.inspect(post));

   });

}).listen(3000);

上面程式碼並沒有在請求響應函式中向客戶端返回資訊。

通過querystring.parse將post解析為真正的POST請求格式

5.http.ServerResponse

http.ServerResponse是返回給客戶端的資訊,決定了使用者最終能看到的結果。它也是由http.Server的request事件傳送的,作為第二個引數傳遞,一般簡稱為response或res。

httpServerResponse有三個重要的成員函式,用於返回響應頭、響應內容以及結束請求。

response.writeHead(statusCode,[headers]):向請求的客戶端傳送響應頭。statusCode是HTTP狀態碼,如:200,404。headers是一個類似關聯陣列的物件,表示響應頭的每個屬性。該函式在一個請求內最多隻能呼叫一次,如果不呼叫,則會自動生成一個響應頭。

response.write(data,[encoding]):向請求的客戶端傳送響應內容。data是一個Buffer或字串,表示要傳送的內容。如果data是字串,那麼需要指定encoding來說明它的編碼方式,預設是utf-8。在response.end呼叫之前,response.write可以被多次呼叫。

response.end([data],[encoding]):結束響應,告知客戶端所有傳送已經完成。當所有返回的內容傳送完畢的時候,該函式必須被呼叫一次。如果不呼叫該函式,客戶端將永遠處於等待狀態。

HTTP客戶端

http模組提供了兩個函式http.request和http.get,功能是作為客戶端向HTTP伺服器發起請求。

http.request(options,callback)發起HTTP請求,接受兩個引數,option是一個類似關聯陣列的物件,表示請求的引數,callback是請求的回撥函式。option常用引數如下:

l  host:請求網站的域名或IP地址。

l  port:請求網站的埠,預設80。

l  method:請求方法,預設是GET

l  path:請求相對根的路徑,預設是“/”QueryString應該包含在其中。

l  headers:一個關聯陣列物件,為請求頭的內容

callback傳遞一個引數,為http.ClientResponse的例項

http.request返回一個http.ClientRequest的例項。如下通過http.request傳送POST請求程式碼:

//httprequest.js

var http =require(‘http’);

var querystring =require(‘querystring’);

var contents =querystring.stringify({

      name:’will’,

      email:’[email protected]’,

      adress:’fsfsdfsdfs’;

});

var options = {

      host:’www.byvoid.com’,

      path:’/application/node/post.php’,

      method:’POST’,

      headers:{

         ‘Content-Type’:’application/x-www.form-urlencoded’,

         ‘Content-Length:contents.length,

      }

};

var req =http.request(options,function(res){

      res.setEncoding(‘utf-8’);

      res.on(‘data’,function(data){

          console.log(data);

      });

});

req.write(contents);

req.end();

http.get(options,callback) http模組還提供了一個更加簡便的方法便於處理GET請求:http.get。它是http.request的簡化版,唯一區別在於http.get自動將請求方法裝置成GET請求,同時不需要手動呼叫req.end();

httpget.js

var http =require(‘http’);

http.get({host:’www.baidu.com’},function(res){

    res.setEncoding(‘utf8’);

    res.on(‘data’,function(data){

           console.log(data);

    });

});

http.ClientRequest

http.ClientRequest是由http.request或http.get返回產生物件,表示一個已經產生而且正在進行中的HTTP請求。它提供一個response事件,http.requesthttp.get第二個引數指定的回撥函式的繫結物件。也可以顯式地繫結這個事件的監聽函式

//httpresponse.js

var http =require(‘http’);

var req =http.get({host:’www.baidu.com’});

req.on(“response”,function(res){

     res.setEncoding(‘utf8’);

     res.on(‘data’,function(data){

             console.log(data);

     }

})

http.ClientRequest像http.ServerResponse一樣也提供了write和end函式,用於向伺服器傳送請求體,通常用於POST、PUT等操作。所有寫結束以後必須呼叫end函式以通知伺服器,否則請求無效。

它還提供以下函式:

request.abort():終止正在傳送的請求

request.setTimeout(timeout,[callback])設定請求超時時間,

request.setNoDelay([noDelay])

request.setSocketKeepAlive([enable],[initialDelay])等函式

http.ClientResponse

http.ClientResponse與http.ServerRequest相似,提供三個事件data,end,和close,分別在資料到達、傳輸結束和連線結束時觸發,其中data事件傳遞一個引數chunk,表示接收到資料。

http.ClientResponse也提供了一些屬性,用於表示請求的結果狀態,

名稱

含義

statusCode

200/404

httpVersion

協議版本

headers

http請求頭

trailers

http請求尾

還提供以下特殊函式:

response.setEncoding([encoding]);當data事件被觸發時,資料將會以encoding編碼。預設值為null,即不編碼,以Buffer形式儲存。常用utf8

response.pause():暫停接收資料和傳送事件,方便實現下載功能

response.resume():從暫停狀態中恢復。