中間件機制能夠讓咱們在一個給定的流程中添加一個處理步驟,從而對這個流程的輸入或者輸出產生影響,或者產生一些中做用、狀態,或者攔截這個流程。中間件機制和tomcat
的過濾器相似,這二者都屬於責任鏈模式的具體實現。express
let express = require('express') let app = express() //解析request 的body app.use(bodyParser.json()) //解析 cookie app.use(cookieParser()) //攔截 app.get('/hello', function (req, res) { res.send('Hello World!'); });
request
的中間件首先模擬一個request
json
request = { //模擬的request requestLine: 'POST /iven_ HTTP/1.1', headers: 'Host:www.baidu.com\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0', requestBody: 'key1=value1&key2=value2&key3=value3', }
一個http
請求分爲請求行、請求頭、和請求體,這三者之間經過\r\n\r\n
即一個空行來分割,這裏假設已經將這三者分開,requestLine
(請求行)中有方法類型,請求url
,http
版本號,這三者經過空格來區分,headers
(請求頭)中的各部分經過\r\n
來分割,requestBody
(請求體)中經過 &
來區分參數數組
模擬中間件機制tomcat
約定 中間件必定是一個函數而且接受 request, response, next三個參數cookie
function App() { if (!(this instanceof App)) return new App(); this.init(); } App.prototype = { constructor: App, init: function() { this.request = { //模擬的request requestLine: 'POST /iven_ HTTP/1.1', headers: 'Host:www.baidu.com\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0', requestBody: 'key1=value1&key2=value2&key3=value3', }; this.response = {}; //模擬的response this.chain = []; //存放中間件的一個數組 this.index = 0; //當前執行的中間件在chain中的位置 }, use: function(handle) { //這裏默認 handle 是函數,而且這裏不作判斷 this.chain.push(handle); }, next: function() { //當調用next時執行index所指向的中間件 if (this.index >= this.chain.length) return; let middleware = this.chain[this.index]; this.index++; middleware(this.request, this.response, this.next.bind(this)); }, }
對 request 處理的中間件app
function lineParser(req, res, next) { let items = req.requestLine.split(' '); req.methond = items[0]; req.url = items[1]; req.version = items[2]; next(); //執行下一個中間件 } function headersParser(req, res, next) { let items = req.headers.split('\r\n'); let header = {} for(let i in items) { let item = items[i].split(':'); let key = item[0]; let value = item[1]; header[key] = value; } req.header = header; next(); //執行下一個中間件 } function bodyParser(req, res, next) { let bodyStr = req.requestBody; let body = {}; let items = bodyStr.split('&'); for(let i in items) { let item = items[i].split('='); let key = item[0]; let value = item[1]; body[key] = value; } req.body = body; next(); //執行下一個中間件 } function middleware3(req, res, next) { console.log('url: '+req.url); console.log('methond: '+req.methond); console.log('version: '+req.version); console.log(req.body); console.log(req.header); next(); //執行下一個中間件 }
let app = App(); app.use(lineParser); app.use(headersParser); app.use(bodyParser); app.use(middleware3); app.next();
function App() { if (!(this instanceof App)) return new App(); this.init(); } App.prototype = { constructor: App, init: function() { this.request = { //模擬的request requestLine: 'POST /iven_ HTTP/1.1', headers: 'Host:www.baidu.com\r\nCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0', requestBody: 'key1=value1&key2=value2&key3=value3', }; this.response = {}; //模擬的response this.chain = []; //存放中間件的一個數組 this.index = 0; //當前執行的中間件在chain中的位置 }, use: function(handle) { //這裏默認 handle 是函數,而且這裏不作判斷 this.chain.push(handle); }, next: function() { //當調用next時執行index所指向的中間件 if (this.index >= this.chain.length) return; let middleware = this.chain[this.index]; this.index++; middleware(this.request, this.response, this.next.bind(this)); }, } function lineParser(req, res, next) { let items = req.requestLine.split(' '); req.methond = items[0]; req.url = items[1]; req.version = items[2]; next(); //執行下一個中間件 } function headersParser(req, res, next) { let items = req.headers.split('\r\n'); let header = {} for(let i in items) { let item = items[i].split(':'); let key = item[0]; let value = item[1]; header[key] = value; } req.header = header; next(); //執行下一個中間件 } function bodyParser(req, res, next) { let bodyStr = req.requestBody; let body = {}; let items = bodyStr.split('&'); for(let i in items) { let item = items[i].split('='); let key = item[0]; let value = item[1]; body[key] = value; } req.body = body; next(); //執行下一個中間件 } function middleware3(req, res, next) { console.log('url: '+req.url); console.log('methond: '+req.methond); console.log('version: '+req.version); console.log(req.body); console.log(req.header); next(); //執行下一個中間件 } let app = App(); app.use(lineParser); app.use(headersParser); app.use(bodyParser); app.use(middleware3); app.next();
將以上總體代碼運行後將打印如下信息函數
url: /iven_ methond: POST version: HTTP/1.1 {key1: "value1", key2: "value2", key3: "value3"} {Host: "www.baidu.com", Cookie: "BAIDUID=E063E9B2690116090FE24E01ACDDF4AD"}