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

从零开始搭建一个Node.js企业级Web服务器(三):中间件

时间:2023-04-03 22:33:34 Node.js

关于中间件广义上的中间件是指能够为操作系统以外的应用程序提供功能的软件,范围从云计算的各种服务厂商针对某个领域的小A检测模块。Express中间件特指基于Express中间件机制提供功能的软件模块。Express在3.x及更早版本中依赖Connect作为底层中间件机制。从4.x版本开始,内置了兼容Connect的中间件机制,因此Express中可以直接使用基于Connect的中间件。Express会以队列的形式组织处理过程。派发请求时,递归传递next方法依次调用处理过程(详见源码):写一个上一章完成的路由校正中间件项目licg9999/nodejs-server-examples-02-validatehas一个小问题,无法访问非标准路径的接口,比如无法访问http://localhost:9000/api//shop:现在使用中间件解决此类问题:$mkdirsrc/middlewares#新建src/middlewares存放自定义中间件的目录$tree-L2-Inode_modules#显示除node_modules以外的目录内容结构。├──Dockerfile├──package.json├──public│├──glue.js│├──index.css│├──index.html│└──index.js├──src│├──控制器│├──中间件│├──模具│├──服务器。js│└──服务└──yarn.lock//src/middlewares/urlnormalize.jsconst{normalize}=require('path');const{parse,format}=require('url');module.exports=functionurlnormalizeMiddleware(){return(req,res,next)=>{//解决在windows和linux系统中normalize路径分隔符使用不一致的问题constpathname=normalize(req.path).split('\\')。加入('/');consturlParsed=parse(req.url);让shouldRedirect=false;//重定向非标准路径if(req.path!=pathname){urlParsed.pathname=路径名;应该重定向=真;}//执行重定方向或策略过if(shouldRedirect){res.redirect(format(urlParsed));}else{下一个();}};};//src/middlewares/index.jsconst{Router}=require('express');consturlnormalizeMiddleware=require('./urlnormalize');module.exports=asyncfunctioninitMiddlewares(){constrouter=路由器();router.use(urlnormalizeMiddleware());返回路由器;};//src/server.jsconstexpress=require('express');const{resolve}=require('path');const{promisify}=require('util');+constinitMiddlewares=require('./middlewares');constinitControllers=require('./controllers');//...asyncfunctionbootstrap(){server.use(express.static(publicDir));server.use('/moulds',express.static(mouldsDir));+server.use(awaitinitMiddlewares());server.use(awaitinitControllers());awaitpromisify(server.listen.bind(server,port))();console.log(`>在端口${port上启动}`);}bootstrap();访问http://localhost:9000/api//shop可以看到自动重定向到有效路由:补充storeadditionlogic目前store管理缺少storeadditionlogic,因为post解析需要依赖在中间件body-parser上,所以本章添加了这个函数执行body-parser安装命令:$yarnaddbody-parser#...infoDirectdependencies└─body-parser@1.19.0#...后端处理://src/services/shop.js//...classShopService{//...+asynccreate({values}){+awaitdelay();++constid=String(+1++Object.keys(memoryStorage).reduce((m,id)=>Math.max(m,id),-Infinity)+);++返回{id,...(memoryStorage[id]=values)};+}}//...//src/controllers/shop.jsconst{Router}=require('express');+constbodyParser=require('body-parser');constshopService=require('../services/shop');const{createShopFormSchema}=require('../moulds/ShopForm');classShopController{shopService;asyncinit(){this.shopService=awaitshopService();常量路由器=路由器();router.get('/',this.getAll);router.get('/:shopId',this.getOne);router.put('/:shopId',this.put);router.delete('/:shopId',this.delete);+router.post('/',bodyParser.urlencoded({extended:false}),this.邮政);返回路由器;}//...+post=async(req,res)=>{+const{name}=req.body;++try{+awaitcreateShopFormSchema().validate({name});+}catch(e){+res.status(400).send({success:false,message:e.message});+return;+}++constshopInfo=awaitthis.shopService.create({values:{name}});++res.send({success:true,data:shopInfo});+};}//...前端处理://public/index.js//...exportasyncfunctionrefreshShopList(){constres=awaitfetch('/api/shop');const{data:shopList}=awaitres.json();consthtmlItems=shopList.map(({id,name})=>`${name}

确认修改删除店铺
`);document.querySelector('#root').innerHTML=`

商店列表:

-${htmlItems.join('')}`;+${htmlItems.join('')}+

添加新商店:

++++确认新增++`;}导出异步函数bindShopInfoEvents(){document.querySelector('#root').addEventListener('click',async(e)=>{e.preventDefault();switch(e.target.dataset.type){case'modify':awaitmodifyShopInfo(e);break;case'remove':awaitremoveShopInfo(e);break;+case'create':+awaitcreateShopInfo(e);+中断;}});}//...+导出异步函数createShopInfo(e){+e.preventDefault();+constname=e.target.parentElement.querySelector('input[name=name]').value;++try{+awaitcreateShopFormSchema().validate({name});+}catch({message}){+e.target.parentElement.querySelector('.error').innerHTML=message;+return;+}++awaitfetch('/api/shop',{+method:'POST',+headers:{+'Content-Type':'application/x-www-form-urlencoded',+},+body:`name=${encodeURIComponent(name)}`,+});++awaitrefreshShopList();+}看看store的新效果:本章源码licg9999/nodejs-server-examples-03-middleware阅读更多从零开始构建Node.js企业Web服务器(零):静态服务从零开始构建Node.js企业Web服务器(一):接口和分层从零开始构建Node.js企业Web服务器(二):验证从零开始搭建一个Node.js企业级Web服务器(三):用中间件从零开始搭建一个Node.js企业级Web服务器(四):从零开始搭建一个Node.js企业级Web服务器,有异常handling(5)):从零开始搭建一个Node.js企业级Web服务器用于数据库访问(6):从零开始搭建一个Node.js企业级Web服务器用于session(7):搭建一个Node.js企业级-levelWebserverfromscratchforauthenticationandlogin(8):NetworkSafelybuildaNode.jsenterprise-levelwebserverfromscratch(九)):配置项从头搭建一个Node.js企业级Web服务器(10):日志从头搭建一个Node.js企业级Web服务器(11):定时任务从头搭建一个Node.js企业级Web服务器scratch(12):从零开始搭建Node.js企业级Web服务器远程调用(13):从零开始搭建Node.js企业级Web服务器断点调试与性能分析(14):搭建Node.jsjs企业级Web服务器从无到有自动化测试服务器(十五):总结与展望