3.使用中间件 | 3. Using middleware

使用中间件

Express是一种路由和中间件Web框架,它具有最小的功能:Express应用本质上是一系列中间件功能调用。

中间件功能是可以访问请求对象(req),响应对象(res)以及应用程序请求 - 响应周期中的下一个中间件功能的函数。下一个中间件函数通常用名为next的变量表示。

中间件功能可以执行以下任务:

  • 执行任何代码。

  • 对请求和响应对象进行更改。

  • 结束请求 - 响应循环。

  • 调用堆栈中的下一个中间件功能。

如果当前的中间件功能没有结束请求 - 响应周期,则它必须调用next()以将控制传递给下一个中间件功能。否则,请求将被挂起。

Express应用程序可以使用以下类型的中间件:

  • Application-level middleware

  • 路由器级中间件

  • 错误处理中间件

  • 内置中间件

  • 第三方中间件

您可以使用可选的装载路径加载应用程序级别和路由器级别的中间件。您还可以将一系列中间件功能一起加载,从而在挂载点处创建中间件系统的子堆栈。

应用程序级中间件

使用app.use()and app.METHOD()函数将应用程序级中间件绑定到应用程序对象的实例,其中METHOD以小写形式是中间件函数处理的请求的HTTP方法(例如GET,PUT或POST)。

这个例子显示了没有安装路径的中间件功能。每次应用程序收到请求时都会执行该功能。

var app = express() app.use(function (req, res, next) { console.log('Time:', Date.now()) next() })

此示例显示/user/:id路径上安装的中间件功能。该函数针对/user/:id路径上的任何类型的HTTP请求执行。

app.use('/user/:id', function (req, res, next) { console.log('Request Type:', req.method) next() })

这个例子显示了一个路由及其处理函数(中间件系统)。该函数处理对/user/:id路径的GET请求。

app.get('/user/:id', function (req, res, next) { res.send('USER') })

下面是一个在装载点加载一系列中间件功能的例子,带有装载路径。它演示了一个中间件子堆栈,用于打印任何类型的HTTP请求到/user/:id路径的请求信息。

app.use('/user/:id', function (req, res, next) { console.log('Request URL:', req.originalUrl) next() }, function (req, res, next) { console.log('Request Type:', req.method) next() })

路由处理程序使您能够为路径定义多个路由。下面的示例为GET请求定义了两个/user/:id路径。第二条路由不会引起任何问题,但它不会被调用,因为第一条路由结束了请求 - 响应周期。

此示例显示处理GET请求到/user/:id路径的中间件子堆栈。

app.get('/user/:id', function (req, res, next) { console.log('ID:', req.params.id) next() }, function (req, res, next) { res.send('User Info') }) // handler for the /user/:id path, which prints the user ID app.get('/user/:id', function (req, res, next) { res.end(req.params.id) })

要跳过路由器中间件堆栈中的其余中间件功能,请调用next('route')以将控制权传递给下一个路由。next('route')仅适用于使用app.METHOD()router.METHOD()功能加载的中间件功能。

此示例显示处理GET请求到/user/:id路径的中间件子堆栈。

app.get('/user/:id', function (req, res, next) { // if the user ID is 0, skip to the next route if (req.params.id === '0') next('route') // otherwise pass the control to the next middleware function in this stack else next() }, function (req, res, next) { // render a regular page res.render('regular') }) // handler for the /user/:id path, which renders a special page app.get('/user/:id', function (req, res, next) { res.render('special') })

路由器级中间件

路由器级中间件的工作方式与应用级中间件的工作方式相同,只是它绑定到一个实例express.Router()

var router = express.Router()

使用router.use()router.METHOD()函数加载路由器级中间件。

以下示例代码通过使用路由器级中间件来复制上面显示的用于应用程序级中间件的中间件系统:

var app = express() var router = express.Router() // a middleware function with no mount path. This code is executed for every request to the router router.use(function (req, res, next) { console.log('Time:', Date.now()) next() }) // a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path router.use('/user/:id', function (req, res, next) { console.log('Request URL:', req.originalUrl) next() }, function (req, res, next) { console.log('Request Type:', req.method) next() }) // a middleware sub-stack that handles GET requests to the /user/:id path router.get('/user/:id', function (req, res, next) { // if the user ID is 0, skip to the next router if (req.params.id === '0') next('route') // otherwise pass control to the next middleware function in this stack else next() }, function (req, res, next) { // render a regular page res.render('regular') }) // handler for the /user/:id path, which renders a special page router.get('/user/:id', function (req, res, next) { console.log(req.params.id) res.render('special') }) // mount the router on the app app.use('/', router)

要跳过路由器的其他中间件功能,请调用next('router')以将控制权从路由器实例中退出。

此示例显示处理GET请求到/user/:id路径的中间件子堆栈。

var app = express() var router = express.Router() // predicate the router with a check and bail out when needed router.use(function (req, res, next) { if (!req.headers['x-auth']) return next('router') next() }) router.get('/', function (req, res) { res.send('hello, user!') }) // use the router and 401 anything falling through app.use('/admin', router, function (req, res) { res.sendStatus(401) })

错误处理中间件

错误处理中间件始终需要四个参数。您必须提供四个参数来将其标识为错误处理中间件功能。即使您不需要使用该next对象,也必须指定它以维护签名。否则,该next对象将被解释为常规中间件,并且将无法处理错误。

使用与其他中间件功能相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数,特别是使用签名(err, req, res, next)):

app.use(function (err, req, res, next) { console.error(err.stack) res.status(500).send('Something broke!') })

有关错误处理中间件的详细信息,请参阅:错误处理。

内置中间件

从版本4.x开始,Express不再依赖于Connect。Express以前包含的中间件功能现在处于独立的模块中; 请参阅中间件功能列表

Express具有以下内置中间件功能:

  • express.static提供静态资产,如HTML文件,图像等。

  • express.json使用JSON有效负载分析传入的请求。注:适用于Express 4.16.0+

  • express.urlencoded使用URL编码的有效负载分析传入的请求。注:适用于Express 4.16.0+

第三方中间件

使用第三方中间件为Express应用程序添加功能。

为所需的功能安装Node.js模块,然后将其加载到应用程序的应用程序级别或路由器级别。

以下示例说明如何安装和加载Cookie解析中间件功能cookie-parser

$ npm install cookie-parser

var express = require('express') var app = express() var cookieParser = require('cookie-parser') // load the cookie-parsing middleware app.use(cookieParser())