淺談express 中間件機制及實現(xiàn)原理
簡介
中間件機制可以讓我們在一個給定的流程中添加一個處理步驟,從而對這個流程的輸入或者輸出產生影響,或者產生一些中作用、狀態(tài),或者攔截這個流程。中間件機制和tomcat的過濾器類似,這兩者都屬于責任鏈模式的具體實現(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!');
});
模擬中間件機制并且模擬實現(xiàn)解析request的中間件
首先模擬一個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',
}
一個http請求分為請求行、請求頭、和請求體,這三者之間通過\r\n\r\n即一個空行來分割,這里假設已經將這三者分開,requestLine(請求行)中有方法類型,請求url,http版本號,這三者通過空格來區(qū)分,headers(請求頭)中的各部分通過\r\n來分割,requestBody(請求體)中通過 & 來區(qū)分參數(shù)
模擬中間件機制
約定 中間件一定是一個函數(shù)并且接受 request, response, next三個參數(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 = []; //存放中間件的一個數(shù)組
this.index = 0; //當前執(zhí)行的中間件在chain中的位置
},
use: function(handle) { //這里默認 handle 是函數(shù),并且這里不做判斷
this.chain.push(handle);
},
next: function() { //當調用next時執(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));
},
}
對 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í)行下一個中間件
}
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í)行下一個中間件
}
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í)行下一個中間件
}
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í)行下一個中間件
}
測試代碼
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 = []; //存放中間件的一個數(shù)組
this.index = 0; //當前執(zhí)行的中間件在chain中的位置
},
use: function(handle) { //這里默認 handle 是函數(shù),并且這里不做判斷
this.chain.push(handle);
},
next: function() { //當調用next時執(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í)行下一個中間件
}
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í)行下一個中間件
}
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í)行下一個中間件
}
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í)行下一個中間件
}
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"}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
npm安裝yarn后找不到y(tǒng)arn報錯的解決過程
這篇文章主要給大家介紹了關于npm安裝yarn后找不到y(tǒng)arn報錯的解決過程,文中通過圖文介紹的非常詳細,對遇到同樣問題的同學具有一定的參考性,需要的朋友可以參考下2023-04-04
基于 Node 實現(xiàn)簡易 serve靜態(tài)資源服務器的示例詳解
靜態(tài)資源服務器(HTTP 服務器)可以將靜態(tài)文件(如 js、css、圖片)等通過 HTTP 協(xié)議展現(xiàn)給客戶端。本文介紹如何基于 Node 實現(xiàn)一個簡易的靜態(tài)資源服務器,感興趣的朋友一起看看吧2022-06-06

