使用中间件
Express 是一个路由和中间件 Web 框架,它本身的功能极少:一个 Express 应用程序本质上就是一系列中间件函数调用。
中间件函数是可以访问请求对象 (req
)、响应对象 (res
) 以及应用程序请求-响应生命周期中下一个中间件函数的函数。下一个中间件函数通常用名为 next
的变量表示。
中间件函数可以执行以下任务:
- 执行任何代码。
- 修改请求和响应对象。
- 终止请求-响应生命周期。
- 调用堆栈中的下一个中间件函数。
如果当前中间件函数没有终止请求-响应生命周期,它必须调用 next()
将控制权传递给下一个中间件函数。否则,请求将处于挂起状态。
Express 应用程序可以使用以下类型的中间件:
您可以使用可选的挂载路径加载应用程序级和路由级中间件。您还可以同时加载一系列中间件函数,这将在挂载点创建一个中间件系统的子堆栈。
应用程序级中间件
通过使用 app.use()
和 app.METHOD()
函数,将应用程序级中间件绑定到 app 对象的实例。其中 METHOD
是中间件函数处理的请求的 HTTP 方法(例如 GET、PUT 或 POST)的小写形式。
此示例显示了一个没有挂载路径的中间件函数。每当应用程序收到请求时,该函数都会执行。
const express = require('express')
const app = express()
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
此示例显示了一个挂载在 /user/:id
路径上的中间件函数。该函数将针对 /user/:id
路径上的任何类型的 HTTP 请求执行。
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
此示例显示了一个路由及其处理函数(中间件系统)。该函数处理对 /user/:id
路径的 GET 请求。
app.get('/user/:id', (req, res, next) => {
res.send('USER')
})
这是在挂载点加载一系列中间件函数(带挂载路径)的示例。它展示了一个中间件子堆栈,用于打印 /user/:id
路径上任何类型的 HTTP 请求的请求信息。
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
路由处理程序允许您为同一路径定义多个路由。下面的示例为对 /user/:id
路径的 GET 请求定义了两个路由。第二个路由不会引起任何问题,但由于第一个路由终止了请求-响应生命周期,因此它永远不会被调用。
此示例显示了一个处理对 /user/:id
路径的 GET 请求的中间件子堆栈。
app.get('/user/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
}, (req, res, next) => {
res.send('User Info')
})
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
res.send(req.params.id)
})
要跳过路由中间件堆栈中其余的中间件函数,请调用 next('route')
将控制权传递给下一个路由。
注意
next('route')
仅在通过 app.METHOD()
或 router.METHOD()
函数加载的中间件函数中有效。
此示例显示了一个处理对 /user/:id
路径的 GET 请求的中间件子堆栈。
app.get('/user/:id', (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()
}, (req, res, next) => {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
res.send('special')
})
中间件也可以在数组中声明以实现可重用性。
此示例显示了一个包含中间件子堆栈的数组,该子堆栈处理对 /user/:id
路径的 GET 请求。
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
res.send('User Info')
})
路由级中间件
路由级中间件的工作方式与应用程序级中间件相同,只不过它绑定到 express.Router()
的实例。
const router = express.Router()
使用 router.use()
和 router.METHOD()
函数加载路由级中间件。
以下示例代码通过使用路由级中间件,复制了上面为应用程序级中间件所示的中间件系统。
const express = require('express')
const app = express()
const router = express.Router()
// a middleware function with no mount path. This code is executed for every request to the router
router.use((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', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (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', (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()
}, (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', (req, res, next) => {
console.log(req.params.id)
res.render('special')
})
// mount the router on the app
app.use('/', router)
要跳过路由器其余的中间件函数,请调用 next('router')
将控制权传递回路由器实例之外。
此示例显示了一个处理对 /user/:id
路径的 GET 请求的中间件子堆栈。
const express = require('express')
const app = express()
const router = express.Router()
// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
if (!req.headers['x-auth']) return next('router')
next()
})
router.get('/user/:id', (req, res) => {
res.send('hello, user!')
})
// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
res.sendStatus(401)
})
错误处理中间件
错误处理中间件始终接受四个参数。您必须提供四个参数才能将其标识为错误处理中间件函数。即使您不需要使用 next
对象,也必须指定它以保持签名。否则,next
对象将被解释为常规中间件,并且无法处理错误。
定义错误处理中间件函数的方式与其他中间件函数相同,只是它们有四个参数而不是三个,具体签名为 (err, req, res, next)
。
app.use((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
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')
// load the cookie-parsing middleware
app.use(cookieParser())
有关与 Express 常用的一部分第三方中间件函数列表,请参阅:第三方中间件。
编辑此页面