视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
浅谈express 中间件机制及实现原理
2020-11-27 22:31:19 责编:小采
文档

简介

中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和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

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(请求体)中通过 & 来区分参数

模拟中间件机制

约定 中间件一定是一个函数并且接受 request, response, 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));
 },
}

对 request 处理的中间件

 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"}

下载本文
显示全文
专题