浅谈express 中间件机制及实现原理
简介
中间件机制可以让我们在一个给定的流程中添加一个处理步骤,从而对这个流程的输入或者输出产生影响,或者产生一些中作用、状态,或者拦截这个流程。中间件机制和tomcat的过滤器类似,这两者都属于责任链模式的具体实现。
express中间件使用案例
letexpress=require('express') letapp=express() //解析request的body app.use(bodyParser.json()) //解析cookie app.use(cookieParser()) //拦截 app.get('/hello',function(req,res){ res.send('HelloWorld!'); });
模拟中间件机制并且模拟实现解析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三个参数
functionApp(){ if(!(thisinstanceofApp)) returnnewApp(); 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; letmiddleware=this.chain[this.index]; this.index++; middleware(this.request,this.response,this.next.bind(this)); }, }
对request处理的中间件
functionlineParser(req,res,next){ letitems=req.requestLine.split(''); req.methond=items[0]; req.url=items[1]; req.version=items[2]; next();//执行下一个中间件 } functionheadersParser(req,res,next){ letitems=req.headers.split('\r\n'); letheader={} for(letiinitems){ letitem=items[i].split(':'); letkey=item[0]; letvalue=item[1]; header[key]=value; } req.header=header; next();//执行下一个中间件 } functionbodyParser(req,res,next){ letbodyStr=req.requestBody; letbody={}; letitems=bodyStr.split('&'); for(letiinitems){ letitem=items[i].split('='); letkey=item[0]; letvalue=item[1]; body[key]=value; } req.body=body; next();//执行下一个中间件 } functionmiddleware3(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();//执行下一个中间件 }
测试代码
letapp=App(); app.use(lineParser); app.use(headersParser); app.use(bodyParser); app.use(middleware3); app.next();
整体代码
functionApp(){ if(!(thisinstanceofApp)) returnnewApp(); 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; letmiddleware=this.chain[this.index]; this.index++; middleware(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]; next();//执行下一个中间件 } functionheadersParser(req,res,next){ letitems=req.headers.split('\r\n'); letheader={} for(letiinitems){ letitem=items[i].split(':'); letkey=item[0]; letvalue=item[1]; header[key]=value; } req.header=header; next();//执行下一个中间件 } functionbodyParser(req,res,next){ letbodyStr=req.requestBody; letbody={}; letitems=bodyStr.split('&'); for(letiinitems){ letitem=items[i].split('='); letkey=item[0]; letvalue=item[1]; body[key]=value; } req.body=body; next();//执行下一个中间件 } functionmiddleware3(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();//执行下一个中间件 } letapp=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"}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。