浅谈express 中间件机制及实现原理
短信预约 -IT技能 免费直播动态提醒
简介
中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和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.comrnCookie:BAIDUID=E063E9B2690116090FE24E01ACDDF4AD:FG=1;BD_HOME=0',
requestBody: 'key1=value1&key2=value2&key3=value3',
}
一个http请求分为请求行、请求头、和请求体,这三者之间通过rnrn即一个空行来分割,这里假设已经将这三者分开,requestLine(请求行)中有方法类型,请求url,http版本号,这三者通过空格来区分,headers(请求头)中的各部分通过rn来分割,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.comrnCookie: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('rn');
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.comrnCookie: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('rn');
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"}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341