浅谈express 中间件机制及实现原理
(编辑:jimmy 日期: 2024/11/20 浏览:3 次 )
简介
中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和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"}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇:JavaScript 通过Ajax 动态加载CheckBox复选框