對於初學者有沒有發覺在查看Node.js官方API的時候很是簡單,只有幾個洋文描述兩下子,沒了,我第一次一口氣看完因此API後,對於第一個示例都有些懵,特別是參數裏的request和response,到底是如何經過參數工做的,若是併發量大如何確保每一個人訪問和提交的數據不干擾等等。都沒有教你具體如何在開發中使用,如何着手寫代碼,給你一個Event 'close',只說了下在服務器關閉時觸發,完了。若是沒有了解EventEmitter的核心事件,可能還真不知道如何抒寫代碼並在開發中真正使用。而http server建立的服務對象已經繼承了EventEmitter,因此能夠直接使用on進行監聽便可。學學util包中的inherits是如何繼承EventEmitter的就應該略知一二了。html
在官方文檔的API中有服務器對象和回調函數參數返回參數的對象,response和request對象各有兩種不一樣。一種是server級別的一種是client級別的。
web
關於HTTP部分大體分爲以下的重要點:數組
直接經過http對象使用的有:服務器
1、http.STATUS_CODES網絡
2、http.createServer併發
3、http.request(http.ClientRequest)
異步
4、http.getsocket
5、http.globalAgent函數
做爲回調參數使用的對象有:
衆所周知,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);
測試鏈接:http://localhost:3000/500 結果輸出 Internal Server Error
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 模塊提供了兩個函數 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(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); })