Node.js HTTP 使用詳解

本文轉自 http://my.oschina.net/antianlu/blog/228511

摘要

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

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

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

關于HTTP部分大致分為如下的重要點:

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

一、http.STATUS_CODES

二善已、http.createServer

三灼捂、http.request(http.ClientRequest)

四、http.get

五换团、http.globalAgent

六悉稠、http.IcomingMessage

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

1.http.serverRequest

2.http.serverResponse

3.http.Agent

一、http.STATUS_CODES

眾所周知艘包,http服務器就是一個狀態(tài)服務器的猛,可以根據狀態(tài)碼來確定服務器是處于請求的什么狀態(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結果輸出Internal?Server?Error

二卦尊、http.createServer

http.createServer是創(chuàng)建一臺web服務器的關鍵所在,是處理請求和回應的主函數(shù)出口和出口舌厨,我們把http.createServer創(chuàng)建的服務對象定義為server.代碼如下岂却。

/**

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

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

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

*?由于server已經繼承了EventEmitter的事件功能裙椭,所以可以使用高級函數(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)建服務器的第二種寫法

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

*@param{Object}?req?是http.IncomingMessag的一個實例躏哩,在keep-alive連接中支持多個請求

*@param{Object}?res?是http.ServerResponse的一個實例

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

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

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

*@param{Object}?socket

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

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

*?說明:關閉服務器時觸發(fā)

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

*?說明:每當收到Expect:?100-continue的http請求時觸發(fā)。?如果未監(jiān)聽該事件婿崭,服務器會酌情自動發(fā)送100?Continue響應拨拓。

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

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

*@param{Object}?req

*@param{Object}?req

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

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

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

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

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

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

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

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

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

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

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

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

*@param{Object}?exception

*@param{Object}?socket

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

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

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

*@param{Number}?port?端口

*@param{String}?host?主機

*@param{Number}?backlog?等待隊列的最大長度滞乙,決定于操作系統(tǒng)平臺妄讯,默認是511

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

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

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

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

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

*@param{String}?path

*@param{Function}?callback

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

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

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

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

*@param{Function}?callback

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

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

*@type{number}

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

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

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

*?設置為0將阻止之后建立的連接的一切自動超時行為

*@param{Number}?msecs

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

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

*@type{number}

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

*?說明:這里的主機將是本地

*@param{Number}?port?端口

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

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

三 男韧、http.request

http 模塊提供了兩個函數(shù) http.request 和 http.get,功能是作為客戶端向 HTTP服務器發(fā)起請求默垄。http.request(options, callback) 發(fā)起 HTTP 請求此虑。接受兩個參數(shù),option 是一個類似關聯(lián)數(shù)組的對象口锭,表示請求的參數(shù)朦前,callback 是請求的回調函數(shù)。option常用的參數(shù)如下所示鹃操。http.request 返回一個 http.ClientRequest 的實例韭寸。

/**?*?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:請求的服務器域名或者IP地址?*?port:端口?*?method:請求方式有POST,GET,INPUT,DELETE,CONNECT,默認為GET?*?path:請求地址荆隘,可包含查詢字符串以及可能存在的錨點恩伺。例如'/index.html?page=12'*?handers:?一個包含請求頭的對象。?*/var?options?={????hostname?:'www.google.com',????port?:80,????method?:'POST',????path?:'/upload',????handers:{}};/**?*?如下特別的消息頭應當注意:?*?發(fā)送'Connection:?keep-alive'頭部將通知Node此連接將保持到下一次請求椰拒。?*?發(fā)送'Content-length'頭將使默認的分塊編碼無效晶渠。?*?發(fā)送'Expect'頭部將引起請求頭部立即被發(fā)送凰荚。?*?通常情況,當發(fā)送'Expect:?100-continue'時褒脯,你需要監(jiān)聽continue事件的同時設置超時便瑟。參見RFC26168.2.3章節(jié)以獲得更多的信息。?*//**?*?說明:官方給出的例子?*?應用場景:模擬客服端請求服務器,是一個HTTP?客戶端工具臼节,用于向?HTTP?服務器發(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)了錯誤(可能是DNS解析、TCP的錯誤养盗、或者HTTP解析錯誤),返回的請求對象上的'error'的事件將被觸發(fā)适篙。req.on('error',function(e){???console.log(e.message);});/**?*?源API:request.write(chunk,?[encoding])?*?說明:發(fā)送正文中的一塊往核。用戶可以通過多次調用這個方法將請求正文以流的方式發(fā)送到服務器。此種情況建議在建立請求時使用['Transfer-Encoding','chunked']請求頭嚷节。?*?@param?{ObjectorString}?chunk?參數(shù)chunk應當是一個整數(shù)數(shù)組或字符串聂儒。?*?@param?{String}?encoding?參數(shù)encoding是可選的,僅在chunk為字符串時可用硫痰。?*/req.write('data\n');/**?*?源API:request.end(chunk,?[encoding])?*?說明:完成本次請求的發(fā)送衩婚。如果正文中的任何一個部分沒有來得及發(fā)送,將把他們全部刷新到流中效斑。如果本次請求是分塊的非春,這個函數(shù)將發(fā)出結束字符'0\r\n\r\n'。如果使用參數(shù)data缓屠,就等于在調用request.write(data,?encoding)之后緊接著調用request.end()奇昙。?*?@param?{ObjectorString}?chunk?參數(shù)chunk應當是一個整數(shù)數(shù)組或字符串。?*?@param?{String}?encoding?參數(shù)encoding是可選的敌完,僅在chunk為字符串時可用储耐。?*?example:?req.end(),req.end('data\n'),req.end('data','utf8'),req.end(chunk)?*/req.end();/**?*?阻止一個請求。(v0.3.8中新增的方法滨溉。)?*/req.abort();/**?*?源API:request.setTimeout(timeout,?[callback])?*?說明:一旦給這個請求分配的是一個socket時此函數(shù)會被調用?*?@param?{Number}?timeout?毫秒?*?@param?{Function}?callback?回到函數(shù)?*/req.setTimeout(1000,function(){});/**?*?源API?:request.setNoDelay([noDelay])?*?說明:默認有一定的延遲什湘,設置為0表示無延遲?*?@param?{Number}?noDelay?*/req.setNoDelay(0)/**?*?源API:request.setSocketKeepAlive([enable],?[initialDelay])?*?????類似同上?*/

四、http.get

http.get(options,

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

的簡化版禽炬,唯一的區(qū)別在于http.get自動將請求方法設為了 GET 請求,同時不需要手動調用 req.end()勤家。

/**

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

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

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

*?應用:服務器端測試客服端請求調試等

*@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);????})

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末乐设,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绎巨,更是在濱河造成了極大的恐慌近尚,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件场勤,死亡現(xiàn)場離奇詭異戈锻,居然都是意外死亡,警方通過查閱死者的電腦和手機和媳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門格遭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人留瞳,你說我怎么就攤上這事拒迅。” “怎么了她倘?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵璧微,是天一觀的道長。 經常有香客問我硬梁,道長前硫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任荧止,我火速辦了婚禮开瞭,結果婚禮上,老公的妹妹穿的比我還像新娘罩息。我一直安慰自己,他們只是感情好个扰,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布瓷炮。 她就那樣靜靜地躺著,像睡著了一般递宅。 火紅的嫁衣襯著肌膚如雪娘香。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天办龄,我揣著相機與錄音烘绽,去河邊找鬼。 笑死俐填,一個胖子當著我的面吹牛安接,可吹牛的內容都是我干的。 我是一名探鬼主播英融,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼盏檐,長吁一口氣:“原來是場噩夢啊……” “哼歇式!你這毒婦竟也來了?” 一聲冷哼從身側響起胡野,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤材失,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硫豆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體龙巨,經...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年熊响,在試婚紗的時候發(fā)現(xiàn)自己被綠了旨别。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡耘眨,死狀恐怖昼榛,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情剔难,我是刑警寧澤胆屿,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站偶宫,受9級特大地震影響非迹,放射性物質發(fā)生泄漏。R本人自食惡果不足惜纯趋,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一憎兽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吵冒,春花似錦纯命、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揪阿,卻和暖如春疗我,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背南捂。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工吴裤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人溺健。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓麦牺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子枕面,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容