Node.js HTTP 使用詳解

本文轉(zhuǎn)自 http://my.oschina.net/antianlu/blog/228511

摘要

翻譯和注釋了http 模塊,講述輸入使用,在什么地方寫代碼

于初學(xué)者有沒有發(fā)覺在查看Node.js官方API的時(shí)候非常簡單,只有幾個(gè)洋文描述兩下子,沒了,我第一次一口氣看完所以API后,對于第一個(gè)示例都有些懵,特別是參數(shù)里的request和response,究竟是如何通過參數(shù)工作的,如果并發(fā)量大如何確保每個(gè)人訪問和提交的數(shù)據(jù)不干擾等等。都沒有教你具體如何在開發(fā)中使用,如何著手寫代碼,給你一個(gè)Event 'close',只說了下在服務(wù)器關(guān)閉時(shí)觸發(fā),完了。如果沒有了解EventEmitter的核心事件,可能還真不知道如何抒寫代碼并在開發(fā)中真正使用。而http server創(chuàng)建的服務(wù)對象已經(jīng)繼承了EventEmitter,所以可以直接使用on進(jìn)行監(jiān)聽即可。學(xué)學(xué)util包中的inherits是如何繼承EventEmitter的就應(yīng)該略知一二了。

在官方文檔的API中有服務(wù)器對象和回調(diào)函數(shù)參數(shù)返回參數(shù)的對象,response和request對象各有兩種不同。一種是server級(jí)別的一種是client級(jí)別的。

關(guān)于HTTP部分大致分為如下的重要點(diǎn):

直接通過http對象使用的有:

一、http.STATUS_CODES

二、http.createServer

三、http.request(http.ClientRequest)

四、http.get

五、http.globalAgent

六、http.IcomingMessage

作為回調(diào)參數(shù)使用的對象有:

1.http.serverRequest

2.http.serverResponse

3.http.Agent

一、http.STATUS_CODES

眾所周知,http服務(wù)器就是一個(gè)狀態(tài)服務(wù)器,可以根據(jù)狀態(tài)碼來確定服務(wù)器是處于請求的什么狀態(tài)。如下列出Node.js status code的全部狀態(tài)對于的解釋。

http:?{STATUS_CODES:?{'100':'Continue','101':'Switching?Protocols','102':'Processing','200':'OK','201':'Created','202':'Accepted','203':'Non-Authoritative?Information','204':'No?Content','205':'Reset?Content','206':'Partial?Content','207':'Multi-Status','300':'Multiple?Choices','301':'Moved?Permanently','302':'Moved?Temporarily','303':'See?Other','304':'Not?Modified','305':'Use?Proxy','307':'Temporary?Redirect','400':'Bad?Request','401':'Unauthorized','402':'Payment?Required','403':'Forbidden','404':'Not?Found','405':'Method?Not?Allowed','406':'Not?Acceptable','407':'Proxy?Authentication?Required','408':'Request?Time-out','409':'Conflict','410':'Gone','411':'Length?Required','412':'Precondition?Failed','413':'Request?Entity?Too?Large','414':'Request-URI?Too?Large','415':'Unsupported?Media?Type','416':'Requested?Range?Not?Satisfiable','417':'Expectation?Failed','418':'I\'m?a?teapot','422':'Unprocessable?Entity','423':'Locked','424':'Failed?Dependency','425':'Unordered?Collection','426':'Upgrade?Required','428':'Precondition?Required','429':'Too?Many?Requests','431':'Request?Header?Fields?Too?Large','500':'Internal?Server?Error','501':'Not?Implemented','502':'Bad?Gateway','503':'Service?Unavailable','504':'Gateway?Time-out','505':'HTTP?Version?Not?Supported','506':'Variant?Also?Negotiates','507':'Insufficient?Storage','509':'Bandwidth?Limit?Exceeded','510':'Not?Extended','511':'Network?Authentication?Required'}}

測試用例:

varhttp?=require('http');http.createServer(function(req,res){varstatus?=?req.url.substr(1);if(?!?http.STATUS_CODES[status])????{????????status?='404';????}????res.writeHeader(status,{'Content-Type':'text/plain'});????res.end(http.STATUS_CODES[status]);}).listen(3000);

測試連接:http://localhost:3000/500結(jié)果輸出Internal?Server?Error

二、http.createServer

http.createServer是創(chuàng)建一臺(tái)web服務(wù)器的關(guān)鍵所在,是處理請求和回應(yīng)的主函數(shù)出口和出口,我們把http.createServer創(chuàng)建的服務(wù)對象定義為server.代碼如下。

/**

*?Created?by?Administrator?on?14-4-29.

*/varhttp?=require('http');/**

*?創(chuàng)建服務(wù)器的兩種寫法,第一種寫法如下

*?由于server已經(jīng)繼承了EventEmitter的事件功能,所以可以使用高級(jí)函數(shù)編寫方式監(jiān)控事件

*@param{Function}?request?event

*/varserver?=?http.createServer(function(req,res){//這里的req為http.serverRequestres.writeHeader(200,{'Content-Type':'text/plain'});????res.end('hello?world');});/**

*?說明:創(chuàng)建服務(wù)器的第二種寫法

*?有關(guān)server對象的事件監(jiān)聽

*@param{Object}?req?是http.IncomingMessag的一個(gè)實(shí)例,在keep-alive連接中支持多個(gè)請求

*@param{Object}?res?是http.ServerResponse的一個(gè)實(shí)例

*/varserver?=newhttp.Server();server.on('request',function(req,res){????res.writeHeader(200,{'Content-Type':'text/plain'});????res.end('hello?world');});/**

*?說明:新的TCP流建立時(shí)出發(fā)。?socket是一個(gè)net.Socket對象。?通常用戶無需處理該事件。

*?特別注意,協(xié)議解析器綁定套接字時(shí)采用的方式使套接字不會(huì)出發(fā)readable事件。?還可以通過request.connection訪問socket。

*@param{Object}?socket

*/server.on('connection',function(socket){});/**

*?源API:?Event:?'close'

*?說明:關(guān)閉服務(wù)器時(shí)觸發(fā)

*/server.on('close',function(){});/**

*?說明:每當(dāng)收到Expect:?100-continue的http請求時(shí)觸發(fā)。?如果未監(jiān)聽該事件,服務(wù)器會(huì)酌情自動(dòng)發(fā)送100?Continue響應(yīng)。

*?處理該事件時(shí),如果客戶端可以繼續(xù)發(fā)送請求主體則調(diào)用response.writeContinue,?如果不能則生成合適的HTTP響應(yīng)(例如,400?請求無效)

*?需要注意到,?當(dāng)這個(gè)事件觸發(fā)并且被處理后,?request?事件將不再會(huì)觸發(fā).

*@param{Object}?req

*@param{Object}?req

*/server.on('checkContinue',function(req,res){});/**

*?說明:如果客戶端發(fā)起connect請求,如果服務(wù)器端沒有監(jiān)聽,那么于客戶端請求的該連接將會(huì)被關(guān)閉

*@param{Object}?req?是該HTTP請求的參數(shù),與request事件中的相同。

*@param{Object}?socket?是服務(wù)端與客戶端之間的網(wǎng)絡(luò)套接字。需要自己寫一個(gè)data事件監(jiān)聽數(shù)據(jù)流

*@param{Object}?head?是一個(gè)Buffer實(shí)例,隧道流的第一個(gè)包,該參數(shù)可能為空。

*/server.on('connect',function(req,socket,head){});/**

*?說明:這個(gè)事件主要是對HTTP協(xié)議升級(jí)為其他協(xié)議后的事件監(jiān)聽,如果服務(wù)器端沒有監(jiān)聽,那么于客戶端請求的該連接將會(huì)被關(guān)閉

*@param{Object}?req?是該HTTP請求的參數(shù),與request事件中的相同。

*@param{Object}?socket?是服務(wù)端與客戶端之間的網(wǎng)絡(luò)套接字。需要自己寫一個(gè)data事件監(jiān)聽數(shù)據(jù)流

*@param{Object}?head?是一個(gè)Buffer實(shí)例,升級(jí)后流的第一個(gè)包,該參數(shù)可能為空。

*/server.on('upgrade',function(req,socket,head){});/**

*?說明:如果一個(gè)客戶端連接觸發(fā)了一個(gè)?'error'?事件,?它就會(huì)轉(zhuǎn)發(fā)到這里

*@param{Object}?exception

*@param{Object}?socket

*/server.on('clientError',function(exception,socket){});/**

*?源API:server.listen(port,?[hostname],?[backlog],?[callback])

*?說明:監(jiān)聽一個(gè)?unix?socket,?需要提供一個(gè)文件名而不是端口號(hào)和主機(jī)名。

*@param{Number}?port?端口

*@param{String}?host?主機(jī)

*@param{Number}?backlog?等待隊(duì)列的最大長度,決定于操作系統(tǒng)平臺(tái),默認(rèn)是511

*@param{Function}?callback?異步回調(diào)函數(shù)

*///server.listen(3000,'localhost',100,function(){});/**

*?源API:server.listen(path,?[callback])

*?說明:啟動(dòng)一個(gè)?UNIX?套接字服務(wù)器在所給路徑?path?上監(jiān)聽連接。

*?可能用處:多路徑或渠道數(shù)據(jù)來源監(jiān)聽分隔

*@param{String}?path

*@param{Function}?callback

*///server.listen('path',function(){})/**

*?源API:server.listen(handle,?[callback])

*?說明:Windows?不支持監(jiān)聽一個(gè)文件描述符。

*@param{Object}?handle?變量可以被設(shè)置為server?或者?socket

*@param{Function}?callback

*///server.listen({},function(){});/**

*?說明:最大請求頭數(shù)目限制,?默認(rèn)?1000?個(gè).?如果設(shè)置為0,?則代表不做任何限制.

*@type{number}

*/server.maxHeadersCount?=1000;/**

*?源API:server.setTimeout(msecs,?callback)

*?說明:為套接字設(shè)定超時(shí)值。如果一個(gè)超時(shí)發(fā)生,那么Server對象上會(huì)分發(fā)一個(gè)'timeout'事件,同時(shí)將套接字作為參數(shù)傳遞。

*?設(shè)置為0將阻止之后建立的連接的一切自動(dòng)超時(shí)行為

*@param{Number}?msecs

*@param*/server.setTimeout(1000,function(){});/**

*?說明:一個(gè)套接字被判斷為超時(shí)之前的閑置毫秒數(shù)。?默認(rèn)?120000?(2?分鐘)

*@type{number}

*/server.timeout?=120000;/**

*?說明:這里的主機(jī)將是本地

*@param{Number}?port?端口

*@param{Function}?callback?異步回調(diào)函數(shù)

*/server.listen(3000,function(){???console.log('Listen?port?3000');});

三 、http.request

http 模塊提供了兩個(gè)函數(shù) http.request 和 http.get,功能是作為客戶端向 HTTP服務(wù)器發(fā)起請求。http.request(options, callback) 發(fā)起 HTTP 請求。接受兩個(gè)參數(shù),option 是一個(gè)類似關(guān)聯(lián)數(shù)組的對象,表示請求的參數(shù),callback 是請求的回調(diào)函數(shù)。option常用的參數(shù)如下所示。http.request 返回一個(gè) http.ClientRequest 的實(shí)例。

/**?*?Created?by?Administrator?on14-4-30.*/var?http?=require('http');var?server?=?http.createServer(function(req,res){}).listen(3000);/**?*?參數(shù)配置?*?@type{{hostname:string,?port:?number,?method:string,?path:string,handers:?{}}}?*?host:請求的服務(wù)器域名或者IP地址?*?port:端口?*?method:請求方式有POST,GET,INPUT,DELETE,CONNECT,默認(rèn)為GET?*?path:請求地址,可包含查詢字符串以及可能存在的錨點(diǎn)。例如'/index.html?page=12'*?handers:?一個(gè)包含請求頭的對象。?*/var?options?={????hostname?:'www.google.com',????port?:80,????method?:'POST',????path?:'/upload',????handers:{}};/**?*?如下特別的消息頭應(yīng)當(dāng)注意:?*?發(fā)送'Connection:?keep-alive'頭部將通知Node此連接將保持到下一次請求。?*?發(fā)送'Content-length'頭將使默認(rèn)的分塊編碼無效。?*?發(fā)送'Expect'頭部將引起請求頭部立即被發(fā)送。?*?通常情況,當(dāng)發(fā)送'Expect:?100-continue'時(shí),你需要監(jiān)聽continue事件的同時(shí)設(shè)置超時(shí)。參見RFC26168.2.3章節(jié)以獲得更多的信息。?*//**?*?說明:官方給出的例子?*?應(yīng)用場景:模擬客服端請求服務(wù)器,是一個(gè)HTTP?客戶端工具,用于向?HTTP?服務(wù)器發(fā)起請求。?*?@param?{Object}?options?*?@param?{Function}?callback?*/var?req?=?http.request(options,function(res){????console.log(res);????console.log('STATUS:'+?res.statusCode);????console.log('HEADERS:'+?JSON.stringify(res.headers));????res.setEncoding('utf8');????res.on('data',function(chunk){???????console.log('BODY'+?chunk);????});});req.on('response',function(){});req.on('connect',function(){});req.on('socket',function(){});req.on('upgrade',function(){});req.on('continue',function(){})//如果在請求過程中出現(xiàn)了錯(cuò)誤(可能是DNS解析、TCP的錯(cuò)誤、或者HTTP解析錯(cuò)誤),返回的請求對象上的'error'的事件將被觸發(fā)。req.on('error',function(e){???console.log(e.message);});/**?*?源API:request.write(chunk,?[encoding])?*?說明:發(fā)送正文中的一塊。用戶可以通過多次調(diào)用這個(gè)方法將請求正文以流的方式發(fā)送到服務(wù)器。此種情況建議在建立請求時(shí)使用['Transfer-Encoding','chunked']請求頭。?*?@param?{ObjectorString}?chunk?參數(shù)chunk應(yīng)當(dāng)是一個(gè)整數(shù)數(shù)組或字符串。?*?@param?{String}?encoding?參數(shù)encoding是可選的,僅在chunk為字符串時(shí)可用。?*/req.write('data\n');/**?*?源API:request.end(chunk,?[encoding])?*?說明:完成本次請求的發(fā)送。如果正文中的任何一個(gè)部分沒有來得及發(fā)送,將把他們?nèi)克⑿碌搅髦?。如果本次請求是分塊的,這個(gè)函數(shù)將發(fā)出結(jié)束字符'0\r\n\r\n'。如果使用參數(shù)data,就等于在調(diào)用request.write(data,?encoding)之后緊接著調(diào)用request.end()。?*?@param?{ObjectorString}?chunk?參數(shù)chunk應(yīng)當(dāng)是一個(gè)整數(shù)數(shù)組或字符串。?*?@param?{String}?encoding?參數(shù)encoding是可選的,僅在chunk為字符串時(shí)可用。?*?example:?req.end(),req.end('data\n'),req.end('data','utf8'),req.end(chunk)?*/req.end();/**?*?阻止一個(gè)請求。(v0.3.8中新增的方法。)?*/req.abort();/**?*?源API:request.setTimeout(timeout,?[callback])?*?說明:一旦給這個(gè)請求分配的是一個(gè)socket時(shí)此函數(shù)會(huì)被調(diào)用?*?@param?{Number}?timeout?毫秒?*?@param?{Function}?callback?回到函數(shù)?*/req.setTimeout(1000,function(){});/**?*?源API?:request.setNoDelay([noDelay])?*?說明:默認(rèn)有一定的延遲,設(shè)置為0表示無延遲?*?@param?{Number}?noDelay?*/req.setNoDelay(0)/**?*?源API:request.setSocketKeepAlive([enable],?[initialDelay])?*?????類似同上?*/

四、http.get

http.get(options,

callback) http 模塊還提供了一個(gè)更加簡便的方法用于處理GET請求:http.get。它是 http.request

的簡化版,唯一的區(qū)別在于http.get自動(dòng)將請求方法設(shè)為了 GET 請求,同時(shí)不需要手動(dòng)調(diào)用 req.end()。

/**

*?Created?by?Administrator?on?14-4-30.

*/varhttp?=require('http');http.createServer(function(req,res){}).listen(3000);/**

*?說明:由于大部分請求是不包含正文的GET請求,Node提供了這個(gè)方便的方法。與http.request()唯一的區(qū)別是此方法將請求方式設(shè)置為GET,并且自動(dòng)調(diào)用req.end()。

*?應(yīng)用:服務(wù)器端測試客服端請求調(diào)試等

*@param{String}?url?有效地址

*@param{Function}?callback

*/http.get('http://www.baidu.com/index.html',function(res){????console.log('get?response?Code?:'+?res.statusCode);}).on('error',function(e){????????console.log("Got?error:?"+?e.message);????})

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容