浅谈Node.js中间件的工作原理
你需要安装一些东西来创建、使用和测试 Express 中间件。首先需要 Node 和 NPM。为确保已经安装,可以运行:
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、虚拟空间、营销软件、网站建设、庆云网站维护、网站推广。npm -v && node -v
你应该看到已安装的 Node 和 NPM 版本。如果出现错误,则需要安装 Node。所有例子都应在 Node ver 8+ 和NPM ver 5+ 下使用。
本文使用了 Express 4.x 版。这很重要,因为从 3.x 版到 4.x 版有重大的更改。
Express中间件:基础首先我们使用 Express 最基本的内置中间件。创建一个新项目并 npm 初始化它…
npm init npm install express --save Create server.js and paste the following code: const express = require('express'); const app = express(); app.get('/', (req, res, next) => { res.send('Welcome Home'); }); app.listen(3000);中间件解决什么问题?为什么要用它?
假设你在 web 网络服务器上正在使用 Node.js 和 Express 运行Web应用程序。在此应用中,你需要登录的某些页面。
当 Web 服务器收到数据请求时,Express 将为你提供一个请求对象,其中包含有关用户及其所请求数据的信息。 Express 还使你可以访问响应对象,可以在Web服务器响应用户之前对其进行修改。这些对象通常缩短为 req,res。
中间件函数是使用相关信息修改 req 和 res 对象的理想场所。例如用户登录后,你可以从数据库中获取其用户详细信息,然后将这些详细信息存储在 res.user
中。
async function userMiddleware (req, res, next) { try { const userData = await getUserData(req.params.id); //see app.get below if(userData) { req.user = userData; next(); } } catch(error) { res.status(500).send(error.message); //replace with proper error handling } }
如果出现错误,并且你不想执行其他代码,则不要调用该函数。请记住在这种情况下要发送响应,否则客户端将会等待响应直到超时。
var app = express(); //your normal route Handlers app.get('/user/:id', userMiddleware, userController);中间件链
你可以在中间件数组中或着通过使用多个 app.use
调用来链接中间件:
app.use(middlewareA); app.use(middlewareB); app.get('/', [middlewareC, middlewareD], handler);
Express 收到请求后,与请求相匹配的每个中间件都将会按照初始化的顺序运行,直到有终止操作为止。
因此,如果发生错误,则将按顺序调用所有用于处理错误的中间件,直到其中一个不再调用 next() 函数调用为止。
Express中间件的类型路由器级中间件,例如:router.use内置中间件,例如:express.static,express.json,express.urlencoded错误处理中间件,例如:app.use(err,req,res,next)第三方中间件,例如:bodyparser、cookieparser路由器级中间件express.Router 使用 express.Router 类创建模块化的、可安装的路由处理。路由实例是一个完整的中间件和路由系统。
你可以用中间件进行日志记录、身份验证等操作。如下所示,以记录用户的最新活动并解析身份验证标头,用它确定当前登录的用户并将其添加到 Request 对象。该函数在程序每次收到请求时执行。如果有错误,它会仅结束响应,而不会调用后续的中间件或路由处理。var router = express.Router() //Load router-level middleware by using the router.use() and router.METHOD() functions. //The following example creates a router as a module, loads a middleware function in it, // defines some routes, and mounts the router module on a path in the main app. var express = require(‘express’); var router = express.Router(); // a middleware function with no mount path. This code is executed for // every request to the router // logging async function logMiddleware (req, res, next) { try { console.log(req.user.id, new Date()); next(); } catch() { res.status(500).send(error.message); } } // authentication async function checkAuthentication(req, res, next) => { // check header or url parameters or post parameters for token const token = req.body.token || req.query.token || req.headers['x-access-token'] || req.headers['authorization']; if (token) { try { // verifies secret req.decoded = await jwt.verify(token, config.secret) let checkUser = await authenticateTokenHelper.getUserDetail(req); // if everything is good, save to request for use in other routes if (checkUser) { req.user = req.decoded next() } else { return res.status(403).json({ message: responseMessage.noAuthorized }) } } catch (err) { return res.status(401).json({ message: responseMessage.invalidToken }) } } else { // if there is no token return res.status(400).json({ message: responseMessage.invalidRequest }) } } router.use(logMiddleware); router.get('/user, checkAuthentication, handler);内置中间件
Express 有以下内置的中间件功能:
express.static
提供静态资源,例如 HTML 文件,图像等。express.json
负载解析用 JSON 传入的请求。express.urlencoded
解析传入的用 URL 编码的有效载荷请求。错误处理中间件错误处理中间件始终采用四个参数(err,req,res,next)。你必须通过提供四个参数来将其标识为错误处理中间件函数。即使你不需要使用 next 对象,也必须指定。否则 next 对象将被解释为常规中间件,并将会无法处理错误。基本签名如下所示:
app.use(function (err, req, res, next) { console.error(err.stack) res.status(500).send('Something broke!') })
例1:
app.get('/users', (req, res, next) => { next(new Error('I am passing you an error!')); }); app.use((err, req, res, next) => { console.log(err); if(!res.headersSent){ res.status(500).send(err.message); } });
在这种情况下,管道末端的错误处理中间件将会处理该错误。你可能还会注意到,我检查了 res.headersSent
属性。这只是检查响应是否已经将标头发送到客户端。如果还没有,它将向客户端发送 HTTP 500 状态和错误消息。
例2:
你还可以链接错误处理中间件。通常以不同的方式处理不同类型的错误:
app.get('/users, (req, res, next) => { let err = new Error('I couldn\\'t find it.'); err.httpStatusCode = 404; next(err); }); app.get('/user, (req, res, next) => { let err = new Error('I\\'m sorry, you can\\'t do that, Dave.'); err.httpStatusCode = 304; next(err); }); app.use((err, req, res, next) => { // handles not found errors if (err.httpStatusCode === 404) { res.status(400).render('NotFound'); } // handles unauthorized errors else if(err.httpStatusCode === 304){ res.status(304).render('Unauthorized'); } // catch all else if (!res.headersSent) { res.status(err.httpStatusCode || 500).render('UnknownError'); } next(err); });在这种情况下,中间件检查是否抛出了 404(not found)错误。如果是,它将渲染 “NotFound” 模板页面,然后将错误传递到中间件中的下一项。下一个中间件检查是否抛出了 304(unauthorized)错误。如果是,它将渲染“Unauthorized”页面,并将错误传递到管道中的下一个中间件。最后,“catch all” 错误处理仅记录错误,如果未发送响应,它将发送错误的 httpStatusCode(如果未提供则发送 HTTP 500 状态)并渲染 “UnknownError” 模板。第三方级别的中间件
在某些情况下,我们将向后端添加一些额外的功能。先安装 Node.js 模块获取所需的功能,然后在应用级别或路由器级别将其加载到你的应用中。
示例:当 body-parser 处理 Content-Type 请求标头时,所有中间件都将使用解析的正文填充 req.body
属性。
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.urlencoded({extended:false})) app.use(bodyParser.json()) app.post('/save',(req,res)=>{ res.json({ "status":true, "payload":req.body }) } app.listen(3000,(req,res)=>{ console.log('server running on port') })总结
中间件功能是一种非常好的方式,可以对每个请求或针对特定路由的每个请求运行代码,并对请求或响应数据采取措施。中间件是现代 Web 服务器的重要组成部分,并且非常有用。
英文原文地址:https://www.thirdrocktechkno.com/blog/how-Node-JS-middleware-works/
为了保证的可读性,本文采用意译而非直译。
更多编程相关知识,请访问:编程入门!!
网站题目:浅谈Node.js中间件的工作原理
网站URL:http://azwzsj.com/article/cgeoeg.html