浅谈express 中间件机制及实现原理

网友投稿 461 2023-04-11


浅谈express 中间件机制及实现原理

简介

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

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: "baidu.com", Cookie: "BAIDUID=E063E9B2690116090FE24E01ACDDF4AD"}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot+maven快速构建项目的示例代码
下一篇:接口设计:建立高效系统的关键步骤
相关文章

 发表评论

暂时没有评论,来抢沙发吧~