Node学习HTTP模块(HTTP 服务器与客户端)
Node學習HTTP模塊(HTTP 服務器與客戶端)
Node.js 標準庫提供了 http 模塊,其中封裝了一個高效的 HTTP 服務器和一個簡易的HTTP 客戶端。http.Server 是一個基于事件的 HTTP 服務器,它的核心由 Node.js 下層 C++部分實現,而接口由JavaScript封裝,兼顧了高性能與簡易性。http.request 則是一個HTTP 客戶端工具,用于向 HTTP 服務器發起請求。
'http'模塊提供兩種使用方式:
-
作為服務端使用時,創建一個HTTP服務器,監聽HTTP客戶端請求并返回響應。
-
作為客戶端使用時,發起一個HTTP客戶端請求,獲取服務端響應。
?以下是node HTTP模塊Api
HTTP http.STATUS_CODES http.createServer([requestListener]) http.createClient([port], [host]) Class: http.Server 事件 : 'request' 事件: 'connection' 事件: 'close' Event: 'checkContinue' 事件: 'connect' Event: 'upgrade' Event: 'clientError' server.listen(port, [hostname], [backlog], [callback]) server.listen(path, [callback]) server.listen(handle, [callback]) server.close([callback]) server.maxHeadersCount server.setTimeout(msecs, callback) server.timeout Class: http.ServerResponse 事件: 'close' response.writeContinue() response.writeHead(statusCode, [reasonPhrase], [headers]) response.setTimeout(msecs, callback) response.statusCode response.setHeader(name, value) response.headersSent response.sendDate response.getHeader(name) response.removeHeader(name) response.write(chunk, [encoding]) response.addTrailers(headers) response.end([data], [encoding]) http.request(options, callback) http.get(options, callback) Class: http.Agent new Agent([options]) agent.maxSockets agent.maxFreeSockets agent.sockets agent.freeSockets agent.requests agent.destroy() agent.getName(options) http.globalAgent Class: http.ClientRequest Event 'response' Event: 'socket' 事件: 'connect' Event: 'upgrade' Event: 'continue' request.write(chunk, [encoding]) request.end([data], [encoding]) request.abort() request.setTimeout(timeout, [callback]) request.setNoDelay([noDelay]) request.setSocketKeepAlive([enable], [initialDelay]) http.IncomingMessage 事件: 'close' message.httpVersion message.headers message.rawHeaders message.trailers message.rawTrailers message.setTimeout(msecs, callback) message.method message.url message.statusCode message.socket一、開篇經典實例
先從一個簡單例子開始,創建一個叫server.js的文件,并寫入以下代碼(服務端):
var http = require("http"); var open = require("child_process");var body = "Hello World";//創建服務 var server = http.createServer(function(req,res){//打印請求方法和請求頭部
console.log(req.method);
console.log(req.headers);
//響應體
//寫響應頭部res.writeHead(200,{'Content-Length':body.length,'Content-Type': 'text/plain;charset=utf-8','access-control-allow-origin':'*'});res.end("Hello World\n"); });server.listen(3000,function(){console.log("sddsf"); });open.exec("start http://127.0.0.1:3000");
運行結果 :Hello World
先從一個簡單例子開始,創建一個叫client.js的文件,并寫入以下代碼(客戶端):
var http = require("http"); var open = require("child_process");var url = "http://www.alloyteam.com"; var options = {host:"pingfan1990.sinaapp.com/",port:'',path: '/',method: 'POST',headers: {'Content-Type': 'application/x-www-form-urlencoded'}}//創建一個請求 var data = ""; var req = http.request(url,function(res){//打印 響應狀態碼和頭部 console.log(res.statusCode);console.log(res.headers);//設置顯示編碼res.setEncoding("utf8");// 數據是 chunked 發送,意思就是一段一段發送過來的// 監聽的'data'事件,是在數據流中監聽的 我們使用 data 給他們串接起來res.on("data",function(chunk){data += chunk;});//響應完畢時間出發,輸出datares.on("end",function(){//console.log(data); });});//設置超時 req.setTimeout(2,function(){ //故意把時間設置很短,觸發超時事件。console.log('請求超時!'); });req.write('Hello World'); //發送請求 req.end();要點分析:
? ?1.調用http模塊提供的函數:"createServer" 。這個函數會返回一個新的web服務器對象。
參數 "requestListener"?是一個函數,它將會自動加入到 "request"?事件的監聽隊列。
當一個request到來時,Event-Loop會將這個Listener回調函數放入執行隊列, node中所有的代碼都是一個一個從執行隊列中拿出來執行的。
這些執行都是在工作線程上(Event Loop本身可以認為在一個獨立的線程中,我們一般不提這個線程,而將node稱呼為一個單線程的執行環境),
所有的回調都是在一個工作線程上運行。
?2.HTTP請求本質上是一個數據流,由請求頭(headers)和請求體(body)組成。例如以下是一個完整的HTTP請求數據內容。
POST / HTTP/1.1 User-Agent: curl/7.26.0 Host: localhost Accept: */* Content-Length: 11 Content-Type: application/x-www-form-urlencodedHello World3.HTTP響應本質上也是一個數據流,同樣由響應頭(headers)和響應體(body)組成。例如以下是一個完整的HTTP請求數據內容。
HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 11 Date: Tue, 05 Nov 2013 05:31:38 GMT Connection: keep-aliveHello World4.在回調函數中,除了可以使用response對象來寫入響應頭數據外response.writeHead方法寫頭部,還能把response對象當作一個只寫數據流來寫入響應體數據。
實例:
var body = 'hello world'; response.writeHead(200, {'Content-Length': body.length,'Content-Type': 'text/plain;charset=utf-8',//設置允許域,可以控制跨越'access-control-allow-origin':'*'});二、http.server的事件
http.Server是http模塊的HTTP服務器對象,用 Node.js 做的所有基于 HTTP 協議的系統,如網站、社交應用甚至代理服務器,都是基于 http.Server 實現的。它提供了一套封裝級別很低的 API,僅僅是流控制和簡單的消息解析,所有的高層功能都要通過它的接口來實現。
1、http.Server 的事件
http.Server 是一個基于事件的 HTTP 服務器,所有的請求都被封裝為獨立的事件,開發者只需要對它的事件編寫響應函數即可實現 HTTP 服務器的所有功能。它繼承自EventEmitter,提供了以下幾個事件。
? ? ? ①request:當客戶端請求到來時,該事件被觸發,提供兩個參數 req 和res,分別是http.ServerRequest 和 http.ServerResponse 的實例,表示請求和響應信息。
? ? ? ②?connection:當 TCP 連接建立時,該事件被觸發,提供一個參數 socket,為net.Socket 的實例。connection 事件的粒度要大于 request,因為客戶端在Keep-Alive 模式下可能會在同一個連接內發送多次請求。
? ? ? ③close :當服務器關閉時,該事件被觸發。注意不是在用戶連接斷開時。除此之外還有 checkContinue、upgrade、clientError 事件,通常我們不需要關心,只有在實現復雜的 HTTP 服務器的時候才會用到。
在這些事件中, 最常用的就是 request 了, 因此 http 提供了一個捷徑:http.createServer([requestListener]) , 功能是創建一個 HTTP 服務器并將requestListener 作為 request 事件的監聽函數,這也是我們前面例子中使用的方法。
事實上它顯式的實現方法是:
var http=require('http'); var server=new http.Server(); server.on('request',function(req,res){res.writeHead(200,{'Content-Type':'text/html'});res.write('<h1>Node.js</h1>');res.end('<p>HelloWorld</p>'); });server.listen(3000); console.log('HTTP SERVER is LISTENING AT PORT 3000.');2、http.ServerRequest
http.ServerRequest 是 HTTP 請求的信息,是后端開發者最關注的內容。它一般由http.Server 的 request 事件發送,作為第一個參數傳遞,通常簡稱 request 或 req。
HTTP 請求一般可以分為兩部分:請求頭(Request Header)和請求體(Requset Body)。以上內容由于長度較短都可以在請求頭解析完成后立即讀取。而請求體可能相對較長,需要一定的時間傳輸,因此 http.ServerRequest 提供了以下3個事件用于控制請求體傳輸。
?①data :當請求體數據到來時,該事件被觸發。該事件提供一個參數 chunk,表示接收到的數據。如果該事件沒有被監聽,那么請求體將會被拋棄。該事件可能會被調用多次。
?②end :當請求體數據傳輸完成時,該事件被觸發,此后將不會再有數據到來。
?③close: 用戶當前請求結束時,該事件被觸發。不同于 end,如果用戶強制終止了傳輸,也還是調用close。
??
3、 獲取 GET 請求內容
注意,http.ServerRequest 提供的屬性中沒有類似于 PHP 語言中的 $_GET 或$_POST 的屬性,那我們如何接受客戶端的表單請求呢?由于 GET 請求直接被嵌入在路徑中,URL是完整的請求路徑,包括了 ? 后面的部分,因此你可以手動解析后面的內容作為 GET請求的參數。Node.js 的 url 模塊中的 parse 函數提供了這個功能。
var http = require('http'); var url = require('url'); var util = require('util');http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end(util.inspect(url.parse(req.url,true))); }).listen(3000);在瀏覽器中輸入http://localhost:3000/user?name=tome&age=23&home=yancheng
即可顯示
{ protocol: null,slashes: null,auth: null,host: null,port: null,hostname: null,hash: null,search: '?name=tome&age=23&home=yancheng',query: { name: 'tome', age: '23', home: 'yancheng' },pathname: '/user',path: '/user?name=tome&age=23&home=yancheng',href: '/user?name=tome&age=23&home=yancheng' }通過 url.parse①,原始的 path 被解析為一個對象,其中 query 就是我們所謂的 GET請求的內容,而路徑則是 pathname。
4、獲取 POST 請求內容
HTTP 協議 1.1 版本提供了8種標準的請求方法,其中最常見的就是 GET 和 POST。相比GET 請求把所有的內容編碼到訪問路徑中,POST 請求的內容全部都在請求體中。http.ServerRequest 并沒有一個屬性內容為請求體,原因是等待請求體傳輸可能是一件耗時的工作,譬如上傳文件。而很多時候我們可能并不需要理會請求體的內容,惡意的 POST請求會大大消耗服務器的資源。所以 Node.js 默認是不會解析請求體的,當你需要的時候,需要手動來做。
var http = require('http'); var querystring = require('querystring'); var util = require('util'); http.createServer(function(req,res){ var post=''; req.on('data',function(chunk){post += chunk;}); req.on('end',function(){post=querystring.parse(post);res.end(util.inspect(post));}); }).listen(3000);5、http.ServerResponse
http.ServerResponse 是返回給客戶端的信息,決定了用戶最終能看到的結果。它也是由 http.Server 的 request 事件發送的,作為第二個參數傳遞,一般簡稱為response 或 res。http.ServerResponse 有三個重要的成員函數,用于返回響應頭、響應內容以及結束請求。
? response.writeHead(statusCode, [headers]):向請求的客戶端發送響應頭。statusCode 是 HTTP 狀態碼,如 200 (請求成功)、404 (未找到)等。headers是一個類似關聯數組的對象,表示響應頭的每個屬性。該函數在一個請求內最多只能調用一次,如果不調用,則會自動生成一個響應頭。
? response.write(data, [encoding]):向請求的客戶端發送響應內容。data 是一個 Buffer 或字符串,表示要發送的內容。如果 data 是字符串,那么需要指定encoding 來說明它的編碼方式,默認是 utf-8。在 response.end 調用之前,
response.write 可以被多次調用。
? response.end([data], [encoding]):結束響應,告知客戶端所有發送已經完成。當要所有返回的內容發送完畢的時候,該函數 必須 被調用一次。它接受兩個可選參數,意義和 response.write 相同。如果不調用該函數,客戶端將永遠處于等待狀態。
三、http客戶端
http 模塊提供了兩個函數 http.request 和 http.get,功能是作為客戶端向 HTTP服務器發起請求。
? http.request(options, callback) 發起 HTTP 請求。接受兩個參數,option 是一個類似關聯數組的對象,表示請求的參數,callback 是請求的回調函數。option常用的參數如下所示。
? host :請求網站的域名或 IP 地址。
? port :請求網站的端口,默認 80。
? method :請求方法,默認是 GET。
? path :請求的相對于根的路徑,默認是“/”。QueryString 應該包含在其中。
例如 /search?query=byvoid。
? headers :一個關聯數組對象,為請求頭的內容。
callback 傳遞一個參數,為 http.ClientResponse 的實例。
http.request 返回一個 http.ClientRequest 的實例。
? http.get(options, callback) http 模塊還提供了一個更加簡便的方法用于處理GET請求:http.get。它是 http.request 的簡化版,唯一的區別在于http.get自動將請求方法設為了 GET 請求,同時不需要手動調用 req.end()。
var http = require('http'); http.get({host: 'www.techman-mrge.com'}, function(res) { res.setEncoding('utf8'); res.on('data', function (data) { console.log(data); }); });1. http.ClientRequest
http.ClientRequest 是由 http.request 或 http.get 返回產生的對象,表示一個已經產生而且正在進行中的 HTTP 請求。它提供一個 response 事件,即 http.request或 http.get 第二個參數指定的回調函數的綁定對象。我們也可以顯式地綁定這個事件的監聽函數:
//httpresponse.js
http.ClientRequest 像 http.ServerResponse 一樣也提供了 write 和 end 函數,用于向服務器發送請求體,通常用于 POST、PUT 等操作。所有寫結束以后必須調用 end函數以通知服務器,否則請求無效。http.ClientRequest 還提供了以下函數。
? request.abort():終止正在發送的請求。
? request.setTimeout(timeout, [callback]):設置請求超時時間,timeout 為毫秒數。當請求超時以后,callback 將會被調用。此外還有request.setNoDelay([noDelay])、request.setSocketKeepAlive([enable], [initialDelay]) 等函數。
2. http.ClientResponse
http.ClientResponse 與 http.ServerRequest 相似,提供了三個事件 data、end和 close,分別在數據到達、傳輸結束和連接結束時觸發,其中 data 事件傳遞一個參數chunk,表示接收到的數據。?
http.ClientResponse 還提供了以下幾個特殊的函數。
? response.setEncoding([encoding]):設置默認的編碼,當 data 事件被觸發時,數據將會以 encoding 編碼。默認值是 null,即不編碼,以 Buffer 的形式存儲。常用編碼為 utf8。
? response.pause():暫停接收數據和發送事件,方便實現下載功能。
? response.resume():從暫停的狀態中恢復。
?
參考資料:
Node.js學習(11)----HTTP服務器與客戶端?http://blog.csdn.net/gxhacx/article/details/12433285
Nodejs使用request模塊讓http請求變簡單?http://itbilu.com/nodejs/npm/NJLUyVB7.html
七天學會NodeJs?http://nqdeng.github.io/7-days-nodejs/#4.2.1
大熊君大話NodeJS之------Http模塊?http://www.cnblogs.com/bigbearbb/p/4213524.html
Node爬蟲 :http://www.cnblogs.com/hustskyking/p/spider-with-node.html
轉載于:https://www.cnblogs.com/pingfan1990/p/4662414.html
總結
以上是生活随笔為你收集整理的Node学习HTTP模块(HTTP 服务器与客户端)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌中国人才流失 遭猎头公司不断挖角
- 下一篇: 关于表单验证中成功则跳转到指定页面否则不