当前位置: 首页 > 后端技术 > Node.js

Express中间件机制及实现原理

时间:2023-04-03 20:58:28 Node.js

介绍中间件机制允许我们在给定的进程中添加一个处理步骤,从而影响进程的输入或输出,或者产生一些中间效果、状态,或者拦截这个进程。中间件机制类似于tomcat的filter,都属于责任链模式的具体实现。express中间件使用案例letexpress=require('express')letapp=express()//解析请求bodyapp.use(bodyParser.json())//解析cookieapp.use(cookieParser())//拦截app.get('/hello',function(req,res){res.send('HelloWorld!');});模拟中间件机制,模拟实现解析请求的中间件首先模拟一个requestRequest={//模拟请求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三个参数functionApp(){if(!(thisinstanceofApp))returnnew应用程序();this.init();}App.prototype={constructor:App,init:function(){this.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',};这个.response={};//模拟响应this.chain=[];//一个存储中间件的数组this.index=0;//当前执行的中间件在链中的位置},use:function(handle){//这里默认handle是一个函数,这里不做判断this.chain.push(handle);},next:function(){//调用next时,执行index指向的中间件if(this.index>=this.chain.length)return;让中间件=this.chain[this.index];这个。索引++;中间件(this.request,this.response,this.next.bind(this));},}中间件函数lineParser(req,res,next){letitems=req.requestLine.split('');req.methond=items[0];req.url=items[1];req.version=items[2];下一个();//执行下一个中间件}functionheadersParser(req,res,next){letitems=req.headers.split('\r\n');让标头={}for(letiinitems){letitem=items[i].split(':');让key=item[0];让价值=项目[1];标头[键]=值;}req.header=header;下一个();//执行下一个中间件}functionbodyParser(req,res,next){letbodyStr=req.requestBody;让身体={};让items=bodyStr.split('&');对于(让我在项目中){让项目=项目[i].split('=');让key=item[0];让价值=项目[1];正文[键]=值;}req.body=body;下一个();//执行下一个中间件}functionmiddleware3(req,res,next){console.log('url:'+req.url);console.log('方法:'+req.methond);console.log('version:'+req.version);console.log(req.body);控制台日志(req.header);下一个();//执行下一个中间件}测试代码letapp=App();app.use(lineParser);app.use(headersParser);app.use(bodyParser);app.use(middleware3);app.next();整体代码functionApp(){if(!(thisinstanceofApp))returnnewApp();这个。初始化();}App.prototype={constructor:App,init:function(){this.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',};这个.response={};//模拟响应this.chain=[];//一个存放中间件的数组this.index=0;//当前执行的中间件在链中的位置},use:function(handle){//这里默认handle是函数,这里不做任何判断this.chain.推(处理);},next:function(){//调用next时,执行index指向的中间件if(this.index>=this.chain.length)return;让中间件=this.chain[this.指数];这个。索引++;中间件(this.request,this.response,this.next.bind(this));},}functionlineParser(req,res,next){letitems=req.requestLine.split('');req.methond=items[0];req.url=items[1];req.version=items[2];下一个();//执行下一个中间件}functionheadersParser(req,res,next){letitems=req.headers.split('\r\n');letheader={}for(letiinitems){letitem=items[i].split(':');让key=item[0];让价值=项目[1];标头[键]=值;}req.header=header;下一个();//执行下一个中间件}functionbodyParser(req,res,next){letbodyStr=req.requestBody;让身体={};让items=bodyStr.split('&');对于(让我在项目中){让项目=项目[i].split('=');让key=item[0];让价值=项目[1];正文[键]=值;}req.body=body;下一个();//执行下一个中间件}functionmiddleware3(req,res,next){console.log('url:'+req.url);console.log('方法:'+req.methond);console.log('version:'+req.version);console.log(req.body);控制台日志(req.header);下一个();//执行下一个中间件}letapp=App();app.use(lineParser);app.use(headersParserrser);app.use(bodyParser);app.use(middleware3);app.next();运行结果上面整体代码运行后,会打印如下信息url:/iven_methond:POSTversion:HTTP/1.1{key1:"value1",key2:"value2",key3:"value3"}{Host:"www.baidu.com",Cookie:"BAIDUID=E063E9B2690116090FE24E01ACDDF4AD"}