Node.js HTTP 使用詳解


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

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

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

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

     一、http.STATUS_CODES

    二、http.createServer

    三、http.request(http.ClientRequest)

    四、http.get

    五、http.globalAgent

    六、http.IcomingMessage

        

    作為回調參數使用的對象有:

    1.http.serverRequest

    2.http.serverResponse

    3.http.Agent

 

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  結果輸出 Internal Server Error 

二、http.createServer

        http.createServer是創建一台web服務器的關鍵所在,是處理請求和回應的主函數出口和出口,我們把http.createServer創建的服務對象定義為server.代碼如下。

 

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

var http = require('http');

/**
 * 創建服務器的兩種寫法,第一種寫法如下
 * 由於server已經繼承了EventEmitter的事件功能,所以可以使用高級函數編寫方式監控事件
 * @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');
});


/**
 * 說明:創建服務器的第二種寫法
 * 有關server對象的事件監聽
 * @param {Object} req 是http.IncomingMessag的一個實例,在keep-alive連接中支持多個請求
 * @param {Object} res 是http.ServerResponse的一個實例
 */
var server = new http.Server();
server.on('request',function(req,res){
    res.writeHeader(200,{'Content-Type':'text/plain'});
    res.end('hello world');
});

/**
 * 說明:新的TCP流建立時出發。 socket是一個net.Socket對象。 通常用戶無需處理該事件。
 * 特別注意,協議解析器綁定套接字時采用的方式使套接字不會出發readable事件。 還可以通過request.connection訪問socket。
 * @param {Object} socket
 */
server.on('connection',function(socket){});

/**
 * 源API: Event: 'close'
 * 說明:關閉服務器時觸發
 */
server.on('close',function(){});

/**
 * 說明:每當收到Expect: 100-continue的http請求時觸發。 如果未監聽該事件,服務器會酌情自動發送100 Continue響應。
 * 處理該事件時,如果客戶端可以繼續發送請求主體則調用response.writeContinue, 如果不能則生成合適的HTTP響應(例如,400 請求無效)
 * 需要注意到, 當這個事件觸發並且被處理后, request 事件將不再會觸發.
 * @param {Object} req
 * @param {Object} req
 */
server.on('checkContinue',function(req,res){});

/**
 * 說明:如果客戶端發起connect請求,如果服務器端沒有監聽,那么於客戶端請求的該連接將會被關閉
 * @param {Object} req 是該HTTP請求的參數,與request事件中的相同。
 * @param {Object} socket 是服務端與客戶端之間的網絡套接字。需要自己寫一個data事件監聽數據流
 * @param {Object} head 是一個Buffer實例,隧道流的第一個包,該參數可能為空。
 */
server.on('connect',function(req,socket,head){});

/**
 * 說明:這個事件主要是對HTTP協議升級為其他協議后的事件監聽,如果服務器端沒有監聽,那么於客戶端請求的該連接將會被關閉
 * @param {Object} req 是該HTTP請求的參數,與request事件中的相同。
 * @param {Object} socket 是服務端與客戶端之間的網絡套接字。需要自己寫一個data事件監聽數據流
 * @param {Object} head 是一個Buffer實例,升級后流的第一個包,該參數可能為空。
 */
server.on('upgrade',function(req,socket,head){});

/**
 * 說明:如果一個客戶端連接觸發了一個 'error' 事件, 它就會轉發到這里
 * @param {Object} exception
 * @param {Object} socket
 */
server.on('clientError',function(exception,socket){});

/**
 * 源API:server.listen(port, [hostname], [backlog], [callback])
 * 說明:監聽一個 unix socket, 需要提供一個文件名而不是端口號和主機名。
 * @param {Number} port 端口
 * @param {String} host 主機
 * @param {Number} backlog 等待隊列的最大長度,決定於操作系統平台,默認是511
 * @param {Function} callback 異步回調函數
 */
//server.listen(3000,'localhost',100,function(){});

/**
 * 源API:server.listen(path, [callback])
 * 說明:啟動一個 UNIX 套接字服務器在所給路徑 path 上監聽連接。
 * 可能用處:多路徑或渠道數據來源監聽分隔
 * @param {String} path
 * @param {Function} callback
 */
//server.listen('path',function(){})

/**
 * 源API:server.listen(handle, [callback])
 * 說明:Windows 不支持監聽一個文件描述符。
 * @param {Object} handle 變量可以被設置為server 或者 socket
 * @param {Function} callback
 */
//server.listen({},function(){});

/**
 * 說明:最大請求頭數目限制, 默認 1000 個. 如果設置為0, 則代表不做任何限制.
 * @type {number}
 */
server.maxHeadersCount = 1000;

/**
 * 源API:server.setTimeout(msecs, callback)
 * 說明:為套接字設定超時值。如果一個超時發生,那么Server對象上會分發一個'timeout'事件,同時將套接字作為參數傳遞。
 * 設置為0將阻止之后建立的連接的一切自動超時行為
 * @param {Number} msecs
 * @param
 */
server.setTimeout(1000,function(){});

/**
 * 說明:一個套接字被判斷為超時之前的閑置毫秒數。 默認 120000 (2 分鍾)
 * @type {number}
 */
server.timeout = 120000;

/**
 * 說明:這里的主機將是本地
 * @param {Number} port 端口
 * @param {Function} callback 異步回調函數
 */
server.listen(3000,function(){
   console.log('Listen port 3000');
});

三 、http.request

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

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

var http = require('http');

var server = http.createServer(function(req,res){

}).listen(3000);

/**
 * 參數配置
 * @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:{}
};

/**
 * 如下特別的消息頭應當注意:
 * 發送'Connection: keep-alive'頭部將通知Node此連接將保持到下一次請求。
 * 發送'Content-length'頭將使默認的分塊編碼無效。
 * 發送'Expect'頭部將引起請求頭部立即被發送。
 * 通常情況,當發送'Expect: 100-continue'時,你需要監聽continue事件的同時設置超時。參見RFC2616 8.2.3章節以獲得更多的信息。
 */

/**
 * 說明:官方給出的例子
 * 應用場景:模擬客服端請求服務器,是一個HTTP 客戶端工具,用於向 HTTP 服務器發起請求。
 * @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(){

})

//如果在請求過程中出現了錯誤(可能是DNS解析、TCP的錯誤、或者HTTP解析錯誤),返回的請求對象上的'error'的事件將被觸發。
req.on('error',function(e){
   console.log(e.message);
});

/**
 * 源API:request.write(chunk, [encoding])
 * 說明:發送正文中的一塊。用戶可以通過多次調用這個方法將請求正文以流的方式發送到服務器。此種情況建議在建立請求時使用['Transfer-Encoding', 'chunked']請求頭。
 * @param {Object or String} chunk 參數chunk應當是一個整數數組或字符串。
 * @param {String} encoding 參數encoding是可選的,僅在chunk為字符串時可用。
 */
req.write('data\n');

/**
 * 源API:request.end(chunk, [encoding])
 * 說明:完成本次請求的發送。如果正文中的任何一個部分沒有來得及發送,將把他們全部刷新到流中。如果本次請求是分塊的,這個函數將發出結束字符'0\r\n\r\n'。如果使用參數data,就等於在調用request.write(data, encoding)之后緊接着調用request.end()。
 * @param {Object or String} chunk 參數chunk應當是一個整數數組或字符串。
 * @param {String} encoding 參數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時此函數會被調用
 * @param {Number} timeout 毫秒
 * @param {Function} callback 回到函數
 */
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 的簡化版,唯一的區別在於http.get自動將請求方法設為了 GET 請求,同時不需要手動調用 req.end()。

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

var http = require('http');

http.createServer(function(req,res){

}).listen(3000);

/**
 * 說明:由於大部分請求是不包含正文的GET請求,Node提供了這個方便的方法。與http.request()唯一的區別是此方法將請求方式設置為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);
    })

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM