淺談express 中間件機(jī)制及實(shí)現(xiàn)原理
簡(jiǎn)介
中間件機(jī)制可以讓我們?cè)谝粋€(gè)給定的流程中添加一個(gè)處理步驟,從而對(duì)這個(gè)流程的輸入或者輸出產(chǎn)生影響,或者產(chǎn)生一些中作用、狀態(tài),或者攔截這個(gè)流程。中間件機(jī)制和tomcat的過(guò)濾器類(lèi)似,這兩者都屬于責(zé)任鏈模式的具體實(shí)現(xiàn)。
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!');
});
模擬中間件機(jī)制并且模擬實(shí)現(xiàn)解析request的中間件
首先模擬一個(gè)request
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',
}
一個(gè)http請(qǐng)求分為請(qǐng)求行、請(qǐng)求頭、和請(qǐng)求體,這三者之間通過(guò)\r\n\r\n即一個(gè)空行來(lái)分割,這里假設(shè)已經(jīng)將這三者分開(kāi),requestLine(請(qǐng)求行)中有方法類(lèi)型,請(qǐng)求url,http版本號(hào),這三者通過(guò)空格來(lái)區(qū)分,headers(請(qǐng)求頭)中的各部分通過(guò)\r\n來(lái)分割,requestBody(請(qǐng)求體)中通過(guò) & 來(lái)區(qū)分參數(shù)
模擬中間件機(jī)制
約定 中間件一定是一個(gè)函數(shù)并且接受 request, response, next三個(gè)參數(shù)
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 = []; //存放中間件的一個(gè)數(shù)組
this.index = 0; //當(dāng)前執(zhí)行的中間件在chain中的位置
},
use: function(handle) { //這里默認(rèn) handle 是函數(shù),并且這里不做判斷
this.chain.push(handle);
},
next: function() { //當(dāng)調(diào)用next時(shí)執(zhí)行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));
},
}
對(duì) request 處理的中間件
function lineParser(req, res, next) {
let items = req.requestLine.split(' ');
req.methond = items[0];
req.url = items[1];
req.version = items[2];
next(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
測(cè)試代碼
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 = []; //存放中間件的一個(gè)數(shù)組
this.index = 0; //當(dāng)前執(zhí)行的中間件在chain中的位置
},
use: function(handle) { //這里默認(rèn) handle 是函數(shù),并且這里不做判斷
this.chain.push(handle);
},
next: function() { //當(dāng)調(diào)用next時(shí)執(zhí)行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(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
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(); //執(zhí)行下一個(gè)中間件
}
let app = App();
app.use(lineParser);
app.use(headersParser);
app.use(bodyParser);
app.use(middleware3);
app.next();
運(yùn)行結(jié)果
將以上整體代碼運(yùn)行后將打印以下信息
url: /iven_
methond: POST
version: HTTP/1.1
{key1: "value1", key2: "value2", key3: "value3"}
{Host: "www.baidu.com", Cookie: "BAIDUID=E063E9B2690116090FE24E01ACDDF4AD"}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
nodejs連接mongodb數(shù)據(jù)庫(kù)實(shí)現(xiàn)增刪改查
本篇文章主要結(jié)合了nodejs操作mongodb數(shù)據(jù)庫(kù)實(shí)現(xiàn)增刪改查,包括對(duì)數(shù)據(jù)庫(kù)的增加,刪除,查找和更新,有興趣的可以了解一下。2016-12-12
node.js中的console.dir方法使用說(shuō)明
這篇文章主要介紹了node.js中的console.dir方法使用說(shuō)明,本文介紹了console.dir的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12
Sequelize中用group by進(jìn)行分組聚合查詢(xún)
大家都知道在SQL查詢(xún)中,分組查詢(xún)是較常用的一種查詢(xún)方式。分組查詢(xún)是指通過(guò)GROUP BY關(guān)鍵字,將查詢(xún)結(jié)果按照一個(gè)或多個(gè)字段進(jìn)行分組,分組時(shí)字段值相同的會(huì)被分為一組。在Node.js基于Sequelize的ORM框架中,同樣支持分組查詢(xún),使用非常簡(jiǎn)單方便。下面來(lái)看看詳細(xì)的介紹。2016-12-12
node.js與C語(yǔ)言 實(shí)現(xiàn)遍歷文件夾下最大的文件,并輸出路徑,大小
這篇文章主要介紹了node.js與C語(yǔ)言 實(shí)現(xiàn)遍歷文件夾下最大的文件,并輸出路徑,大小的相關(guān)資料,需要的朋友可以參考下2017-01-01
Node.js重新刷新session過(guò)期時(shí)間的方法
在Node.js中,我們通常使用express-session這個(gè)包來(lái)使用和管理session,保存服務(wù)端和客戶(hù)端瀏覽器之間的會(huì)話狀態(tài)。那如何才能實(shí)現(xiàn)當(dāng)用戶(hù)刷新當(dāng)前頁(yè)面或者點(diǎn)擊頁(yè)面上的按鈕時(shí)重新刷新session的過(guò)期時(shí)間呢,接下來(lái)通過(guò)本文一起學(xué)習(xí)吧2016-02-02
node.js中的buffer.copy方法使用說(shuō)明
這篇文章主要介紹了node.js中的buffer.copy方法使用說(shuō)明,本文介紹了buffer.copy的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12
基于npm?install或run時(shí)一些報(bào)錯(cuò)的解決方案
這篇文章主要介紹了基于npm?install或run時(shí)一些報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

