#Node.js HTTP 使用詳解
關於HTTP部分大致分爲如下的重要點:
直接通過http對象使用的有:
1. http.STATUS_CODES
2. http.createServer
3. http.request(http.ClientRequest)
4. http.get
5. http.globalAgent
6. http.IcomingMessage
####作爲回調參數使用的對象有:
1. http.serverRequest
2. http.serverResponse
3. http.Agent
http.STATUS_CODES
衆所周知,http服務器就是一個狀態服務器,可以根據狀態碼來確定服務器是處於請求的什麼狀態。
如下列出Node.js status code的全部狀態對於的解釋。
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);
結果輸出 Internal Server Error
http.createServer
http.createServer是創建一臺web服務器的關鍵所在,是處理請求和迴應的主函數出口和出口。
我們把http.createServer創建的服務對象定義爲server.代碼如下。
/ 引入 http 模塊
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 請求。
1. 接受兩個參數,
2. option 是一個類似關聯數組的對象,表示請求的參數,-option常用的參數如下所示。
3. callback 是請求的回調函數。
#### http.request 返回一個 http.ClientRequest 的實例。
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()。
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);
})