浅谈 Node.js 中间件的工作原理
什么是 Express 中间件?
- 中间件在字面上的意思是你在软件的一层和另一层中间放置的任何东西。
- Express 中间件是在对 Express 服务器请求的生命周期内所执行的函数。
- 每个中间件都可以访问其被附加到的所有路由的 HTTP 请求和响应。
- 另外,中间件可以终止 HTTP 请求,也可以用 next 将其传递给另一个中间件函数。中间件的这种“链”使你可以对代码进行划分并创建可重用的中间件。
编写 Express 中间件的要求
你需要安装一些东西来创建、使用和测试 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 中间件的工作原理的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

tomcat中间件原理是基于Java Servlet和Java EE规范来实现的。Tomcat作为一个Servlet容器,负责处理HTTP请求和响应,提供Web应用程序的运行环境。Tomcat中间件的原理主要涉及:1、容器模型;2、组件化架构;3、Servlet处理机制;4、事件监听和过滤器;5、配置管理;6、安全性;7、集群和负载均衡;8、连接器技术;9、嵌入式模式等等。

如何在Laravel中使用中间件处理表单验证,需要具体代码示例引言:在Laravel中,表单验证是非常常见的任务。为了确保用户输入的数据的有效性和安全性,我们通常会对表单提交的数据进行验证。Laravel提供了一个方便的表单验证功能,同时也支持使用中间件来处理表单验证。本文将详细介绍如何在Laravel中使用中间件处理表单验证,并提供具体的代码示例

如何在Laravel中使用中间件进行数据加速引言:在使用Laravel框架开发Web应用程序时,数据加速是提高应用性能的关键。中间件是Laravel提供的一个重要功能,可以在请求到达控制器之前或响应返回之前对请求进行处理。本文将重点介绍如何在Laravel中使用中间件实现数据加速,并提供具体的代码示例。一、什么是中间件中间件是Laravel框架中一种机制,用

如何在Laravel中使用中间件进行响应转换中间件是Laravel框架中非常强大且实用的功能之一。它允许我们在请求进入控制器之前或响应被发送给客户端之前,对请求和响应进行处理。在本文中,我将演示如何使用中间件在Laravel中进行响应转换。在开始之前,确保你已经安装了Laravel并创建了一个新的项目。现在,我们将按照以下步骤进行操作:创建一个新的中间件打开

Laravel是一个流行的PHPWeb应用程序框架,提供了许多快速而又简单的方式来构建高效、安全和可扩展的Web应用程序。在开发Laravel应用程序时,我们经常需要考虑数据恢复的问题,即如何在数据丢失或损坏的情况下恢复数据并保证应用程序的正常运行。在本文中,我们将介绍如何使用Laravel中间件来实现数据恢复功能,并提供具体的代码示例。一、什么是Lara

在Slim框架中使用中间件(Middleware)设置跨域资源共享(CORS)的方法跨域资源共享(CORS)是一种机制,允许服务器在HTTP响应头中设置一些额外的信息,来告知浏览器是否允许跨域请求。在一些前后端分离的项目中,使用CORS机制可以实现前端跨域请求后端接口的需求。在使用Slim框架开发RESTAPI时,我们可以使用中间件(Middleware)

如何在Laravel中使用中间件进行定时任务调度引言:Laravel是一款流行的PHP开源框架,提供了便捷且强大的工具来开发Web应用程序。其中一个重要的特性是定时任务调度,它可以让开发者在指定的时间间隔内运行特定的任务。在本文中,我们将介绍如何使用中间件来实现Laravel的定时任务调度,并提供具体的代码示例。环境准备在开始之前,我们需要确保

CodeIgniter中间件:提供安全的文件上传和下载功能引言:在Web应用程序开发过程中,文件上传和下载是非常常见的功能。然而,对于安全性的考虑,处理文件上传和下载通常需要额外的安全措施。CodeIgniter是一个流行的PHP框架,提供了丰富的工具和库来支持开发者构建安全可靠的Web应用程序。本文将介绍如何使用CodeIgniter中间件来实现安全的文件
