Node中提供了http模塊,其中封裝了高效的http服務器和http客戶端
http.server是一個基於事件的HTTP服務器,內部是由c++實現的,接口由JavaScript封裝
http.request是一個HTTP客戶端工具。用戶向服務器發送數據。
下面就來分別得介紹一下http的服務端和客戶端javascript
http.Server實現的,它提供了一套封裝級別很低的API,僅僅是流控制和簡單的解析,全部的高層功能都須要經過它的接口。
下面分別來說一個有關http服務器的幾個事件html
http.server是一個基於事件的HTTP服務器,全部的請求都被封裝到獨立的事件當中,咱們只須要對他的事件編寫相應的行數就能夠實現HTTP服務器的全部功能,它繼承自EventEmitter
,提供瞭如下的事件:
1. request:當客戶端請求到來的時候,該事件被觸發,提供兩個參數request
和response
,分別是http.ServerRequest
和http.ServerResponse
表示請求和響應的信息。
2. connection:當TCP創建鏈接的時候,該事件被觸發,提供了一個參數socket
,爲net.socket
的實例(底層協議對象)
3. close:當服務器關閉的時候會被觸發
4. 除此以外還有checkContinue、upgrade、clientError等事件
咱們最經常使用的仍是request
事件,http也給這個事件提供了一個捷徑:http.createServer([requestListener])
下面咱們來簡單的看一下兩個案例:
第一個是使用request
事件的:前端
const http = require('http'); const net = require('net'); const util = require('util'); //隨便定義的一個函數,下面會用到 function a(){ console.log("dajiahao"); } var server = new http.Server(); server.on('request',(req,res)=>{ console.log(req.url); //設置應答頭信息 res.writeHead(200,{'Content-Type':'text/html'}); res.write('hello we are family<br>'); res.end('server already end\n'); }); //顯示了三次這也證實了TCP的三次握手 server.on('connection',()=>{ a(); }); server.on('close',()=>{ console.log('server will close'); }); //關閉服務爲了觸發close事件 server.close(); server.listen(8080);
下面的案例使用http的給的捷徑http.createServer
製做的代碼:java
const http = require('http'); const net = require('net'); const util = require('util'); http.createServer(function(req,res){ res.writeHead(404,{'Content-Type':'text/plain'}) res.write("we are is content"); res.end("fdsa"); }).listen(3000);
咱們都知道HTTP請求分爲兩部分:請求頭
和請求體
,若是請求的內容少的話就直接在請求頭協議完成以後當即讀取,請求體可能相對較長一點,須要必定的時間傳輸。所以提供了三個事件用於控制請求體傳輸
.
(1)data:當請求體數據到來時,該事件被觸發,該事件一共一個參數chunk,表示接受到的數據。
(2)end:當請求體數據傳輸完成時,該事件被觸發,此後將不會再有數據到來。
(3)close:用戶當前請求結束時,該事件被觸發,不一樣於end,若是用戶強制終止了傳輸,也會觸發close
ServerRequest
的屬性c++
名稱 | 含義 |
ccomplete | 客戶端請求是否已經發送完成 |
httpVersion | HTTP協議版本,一般是1.0或1.1 |
method | HTTP請求方法,如:GET,POST |
url | 原始的請求路徑 |
headers | HTTP請求頭 |
trailers | HTTP請求尾(不常見) |
connection | 當前HTTP鏈接套接字,爲net.Socket的實例 |
socket | connection屬性的別名 |
client | client屬性的別名 |
http.createServer(function(req,res){ console.log(req.httpVersion); //console.log(req.socket); console.log(req.headers); console.log(req.method); res.writeHead(404,{'Content-Type':'text/plain'}) res.write("we are is content"); res.end("fdsa"); }).listen(8080);
因爲GET請求直接被嵌入在路徑中,URL完整的請求路徑,包括了?後面的部分,所以你能夠手動解析後面的內容做爲GET的參數,Nodejs的url模塊中的parse函數提供了這個功能json
const http = require('http'); const net = require('net'); const url = require('url'); const util = require('util'); http.createServer((req,res)=>{ res.write(util.inspect(url.parse(req.url,true))); //利用url模塊去解析客戶端發送過來的URL res.end(util.inspect(url.parse(req.url,false))); }).listen(8080);
POST請求的內容所有都在請求體中,http.ServerRequest並無一個屬性內容爲請求體,緣由是等待請求體傳輸多是一件耗時的工做。譬如上傳文件。惡意的POST請求會大大消耗服務器的資源。因此Nodejs是不會解析請求體,當你須要的時候,須要手動來作。
簡單的看一下代碼:數組
const http = require('http'); const net = require('net'); const url = require('url'); const util = require('util'); //querystring用於處理URL中的查詢字符串 const querystring = require('querystring'); http.createServer((req,res)=>{ var posr = ''; req.on('data',(chunk)=>{ post+=chunk; }); res,on('end',()=>{ //將字符串變爲json的格式 post = querystring.parse(post); //向前端返回字符串 res.end(util.inspect(post)); }); })
決定了用戶最終能到的結果,它是由http.Server的request事件發送的,做爲第二個參數傳遞。通常爲response或res
主要的三個函數:
response.writeHead(statusCode,[headers]):向請求的客戶端發送響應頭。
statusCode是HTTP的狀態碼,如200爲成功,404未找到等。
headers是一個相似關聯數組的對象,表示響應頭的每一個屬性。
response.write(data,[encoding]) 向請求客戶端發送相應內容,data是buffer或字符串,encoding爲編碼
response.end([data],[encoding]) 結束響應,告知用戶全部發送已經完成,當全部要返回的內容發送完畢,該函數必須被調用一次,若是不調用,客戶端永遠處於等待狀態
服務器