5-2 Node.js HTTP 使用詳解

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

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

  • http.STATUS_CODES
  • http.createServer
  • http.request(http.ClientRequest)
  • http.get
  • http.globalAgent
  • http.IcomingMessage

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

  • http.serverRequest
  • http.serverResponse
  • 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'
    }
}

測試用例:

var http = require('http');

http.createServer(function(req, res) {
    var status = 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)建一臺web服務(wù)器的關(guān)鍵所在损俭,是處理請求和回應(yīng)的主函數(shù)出口和出口辣恋。
我們把http.createServer創(chuàng)建的服務(wù)對象定義為server.代碼如下。


// 引入 http 模塊
var http = require('http');


/**
 * 創(chuàng)建服務(wù)器的兩種寫法羔沙,第一種寫法如下
 * 由于server已經(jīng)繼承了EventEmitter的事件功能躺涝,所以可以使用高級函數(shù)編寫方式監(jiān)控事件
 * @param {Function} request event
*/
var server = http.createServer(function(req, res) {
    //這里的req為http.serverRequest
    res.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í)例
 */
var server = new http.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í)采用的方式使套接字不會出發(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ù)器會酌情自動發(fā)送100 Continue響應(yīng)俺猿。
 * 處理該事件時(shí),如果客戶端可以繼續(xù)發(fā)送請求主體則調(diào)用response.writeContinue格仲, 如果不能則生成合適的HTTP響應(yīng)(例如押袍,400 請求無效)
 * 需要注意到, 當(dāng)這個(gè)事件觸發(fā)并且被處理后, request 事件將不再會觸發(fā).
 * @param {Object} req
 * @param {Object} req
 */
server.on('checkContinue',
function(req, res) {});



/**
 * 說明:如果客戶端發(fā)起connect請求,如果服務(wù)器端沒有監(jiān)聽凯肋,那么于客戶端請求的該連接將會被關(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é)議升級為其他協(xié)議后的事件監(jiān)聽药磺,如果服務(wù)器端沒有監(jiān)聽,那么于客戶端請求的該連接將會被關(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('upgrade',
function(req, socket, head) {});



/**
 * 說明:如果一個(gè)客戶端連接觸發(fā)了一個(gè) 'error' 事件, 它就會轉(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è)文件名而不是端口號和主機(jī)名放案。
 * @param {Number} port 端口
 * @param {String} host 主機(jī)
 * @param {Number} backlog 等待隊(duì)列的最大長度,決定于操作系統(tǒng)平臺矫俺,默認(rèn)是511
 * @param {Function} callback 異步回調(diào)函數(shù)
 */
server.listen(3000,'localhost',100,function(){});



/**
 * 源API:server.listen(path, [callback])
 * 說明:啟動一個(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對象上會分發(fā)一個(gè)'timeout'事件,同時(shí)將套接字作為參數(shù)傳遞铅匹。
 * 設(shè)置為0將阻止之后建立的連接的一切自動超時(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ù)再姑,-option常用的參數(shù)如下所示。
  • callback 是請求的回調(diào)函數(shù)找御。

http.request 返回一個(gè) http.ClientRequest 的實(shí)例元镀。


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í)。參見RFC2616 8.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)了錯誤(可能是DNS解析氢拥、TCP的錯誤、或者HTTP解析錯誤)锨侯,返回的請求對象上的'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 {Object or String} 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)克⑿碌搅髦醒H绻敬握埱笫欠謮K的,這個(gè)函數(shù)將發(fā)出結(jié)束字符'0\r\n\r\n'蹬昌。如果使用參數(shù)data混驰,就等于在調(diào)用request.write(data, encoding)之后緊接著調(diào)用request.end()。
 * @param {Object or String} 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ù)會被調(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自動將請求方法設(shè)為了 GET 請求,同時(shí)不需要手動調(diào)用 req.end()轰枝。

var http = require('http');

http.createServer(function(req, res) {

}).listen(3000);

/**
 * 說明:由于大部分請求是不包含正文的GET請求捅彻,Node提供了這個(gè)方便的方法。與http.request()唯一的區(qū)別是此方法將請求方式設(shè)置為GET鞍陨,并且自動調(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);
})

本文系轉(zhuǎn)載,如有侵犯版權(quán)問題诚撵,請通知缭裆。本人立即刪除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寿烟,一起剝皮案震驚了整個(gè)濱河市澈驼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筛武,老刑警劉巖缝其,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異徘六,居然都是意外死亡氏淑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進(jìn)店門硕噩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缭贡,你說我怎么就攤上這事炉擅。” “怎么了阳惹?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵谍失,是天一觀的道長。 經(jīng)常有香客問我莹汤,道長快鱼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮抹竹,結(jié)果婚禮上线罕,老公的妹妹穿的比我還像新娘。我一直安慰自己窃判,他們只是感情好钞楼,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著袄琳,像睡著了一般询件。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唆樊,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天宛琅,我揣著相機(jī)與錄音,去河邊找鬼逗旁。 笑死嘿辟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痢艺。 我是一名探鬼主播仓洼,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼堤舒!你這毒婦竟也來了色建?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤舌缤,失蹤者是張志新(化名)和其女友劉穎箕戳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體国撵,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陵吸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了介牙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壮虫。...
    茶點(diǎn)故事閱讀 40,928評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖环础,靈堂內(nèi)的尸體忽然破棺而出囚似,到底是詐尸還是另有隱情,我是刑警寧澤线得,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布饶唤,位于F島的核電站,受9級特大地震影響贯钩,放射性物質(zhì)發(fā)生泄漏募狂。R本人自食惡果不足惜办素,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祸穷。 院中可真熱鬧性穿,春花似錦、人聲如沸粱哼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揭措。三九已至胯舷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绊含,已是汗流浹背桑嘶。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留躬充,地道東北人逃顶。 一個(gè)月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像充甚,于是被迫代替她去往敵國和親以政。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容