Middleware functions are functions that have access to the request object (中间件功能是可以访问请求对象(req
), the response object (res
), and the next
function in the application’s request-response cycle. req
)、响应对象(res
)和应用程序请求-响应周期中的next
函数的功能。The next
function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.next
函数是Express路由中的一个函数,当调用该函数时,它将执行继当前中间件之后的中间件。
Middleware functions can perform the following tasks:中间件功能可以执行以下任务:
If the current middleware function does not end the request-response cycle, it must call 如果当前中间件函数没有结束请求-响应周期,它必须调用next()
to pass control to the next middleware function. next()
将控制权传递给下一个中间件函数。Otherwise, the request will be left hanging.否则,请求将挂起。
The following figure shows the elements of a middleware function call:下图显示了中间件函数调用的元素:
![]() |
Starting with Express 5, middleware functions that return a Promise will call 从Express5开始,返回承诺的中间件函数在拒绝或抛出错误时将调用next(value)
when they reject or throw an error. next(value)
。next
will be called with either the rejected value or the thrown Error.next
将使用拒绝的值或抛出的错误调用。
Here is an example of a simple “Hello World” Express application. 下面是一个简单的“Hello World”Express应用程序的示例。The remainder of this article will define and add three middleware functions to the application: one called 本文的其余部分将定义并向应用程序添加三个中间件功能:一个称为myLogger
that prints a simple log message, one called requestTime
that displays the timestamp of the HTTP request, and one called validateCookies
that validates incoming cookies.myLogger
,用于打印简单的日志消息;一个称为requestTime
,用于显示HTTP请求的时间戳;另一个称为validateCookies
,用于验证传入的Cookie。
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Here is a simple example of a middleware function called “myLogger”. 下面是一个名为“myLogger”的中间件函数的简单示例。This function just prints “LOGGED” when a request to the app passes through it. 当应用程序的请求通过该函数时,该函数仅打印“已记录”。The middleware function is assigned to a variable named 中间件函数被分配给名为myLogger
.myLogger
的变量。
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
Notice the call above to 注意上面对next()
. next()
的调用。Calling this function invokes the next middleware function in the app. 调用此函数将调用应用程序中的下一个中间件函数。The next()
function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. next()
函数不是Node.js或Express API的一部分,而是传递给中间件函数的第三个参数。The next()
function could be named anything, but by convention it is always named “next”. next()
函数可以被命名为任何名称,但按照惯例,它总是被命名为“next”。To avoid confusion, always use this convention.为避免混淆,请始终使用此约定。
要从路由中间件堆栈中跳过其余中间件功能,请调用next('route')
将控制权传递给下一条路由(相当于调用函数的return
语句)。
To load the middleware function, call 要加载中间件函数,请调用app.use()
, specifying the middleware function. app.use()
,指定中间件函数。For example, the following code loads the 例如,以下代码在路由到根路径(/)之前加载myLogger
middleware function before the route to the root path (/).myLogger
中间件函数。
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Every time the app receives a request, it prints the message “LOGGED” to the terminal.每次应用程序收到请求时,都会将消息“LOGGED”打印到终端。
The order of middleware loading is important: middleware functions that are loaded first are also executed first.中间件加载的顺序很重要:首先加载的中间件功能也会首先执行。
If 如果在路由到根路径之后加载myLogger
is loaded after the route to the root path, the request never reaches it and the app doesn’t print “LOGGED”, because the route handler of the root path terminates the request-response cycle.myLogger
,则请求永远不会到达它,并且应用程序不会打印“已记录”,因为根路径的路由处理程序会终止请求响应周期。
The middleware function 中间件函数myLogger
simply prints a message, then passes on the request to the next middleware function in the stack by calling the next()
function.myLogger
只需打印一条消息,然后通过调用next()
函数将请求传递给堆栈中的下一个中间件函数。
Next, we’ll create a middleware function called “requestTime” and add a property called 接下来,我们将创建一个名为“requestTime”的中间件函数,并向请求对象添加一个名为requestTime
to the request object.requestTime
的属性。
var requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
The app now uses the 该应用程序现在使用requestTime
middleware function. requestTime
中间件功能。Also, the callback function of the root path route uses the property that the middleware function adds to 此外,根路径路由的回调函数使用中间件函数添加到req
(the request object).req
(请求对象)的属性。
var express = require('express')
var app = express()
var requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
app.use(requestTime)
app.get('/', function (req, res) {
var responseText = 'Hello World!<br>'
responseText += '<small>Requested at: ' + req.requestTime + '</small>'
res.send(responseText)
})
app.listen(3000)
When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.当您向应用程序的根用户发出请求时,应用程序现在会在浏览器中显示您请求的时间戳。
Finally, we’ll create a middleware function that validates incoming cookies and sends a 400 response if cookies are invalid.最后,我们将创建一个中间件函数,用于验证传入的cookie,如果cookie无效,则发送400响应。
Here’s an example function that validates cookies with an external async service.下面是一个使用外部异步服务验证cookie的示例函数。
async function cookieValidator (cookies) {
try {
await externallyValidateCookie(cookies.testCookie)
} catch {
throw new Error('Invalid cookies')
}
}
Here we use the 在这里,我们使用cookie-parser
middleware to parse incoming cookies off the req
object and pass them to our cookieValidator
function. cookie-parser
中间件来解析来自req对象的传入cookie,并将它们传递给我们的cookieValidator函数。The validateCookies
middleware returns a Promise that upon rejection will automatically trigger our error handler.validateCookies
中间件返回一个承诺,即拒绝后将自动触发错误处理程序。
var express = require('express')
var cookieParser = require('cookie-parser')
var cookieValidator = require('./cookieValidator')
var app = express()
async function validateCookies (req, res, next) {
await cookieValidator(req.cookies)
next()
}
app.use(cookieParser())
app.use(validateCookies)
// error handler
app.use(function (err, req, res, next) {
res.status(400).send(err.message)
})
app.listen(3000)
Note how 注意如何在next()
is called after await cookieValidator(req.cookies)
. await cookieValidator(req.cookies)
之后调用next()
。This ensures that if 这确保了如果cookieValidator
resolves, the next middleware in the stack will get called. cookieValidator
解析,堆栈中的下一个中间件将被调用。If you pass anything to the 如果将任何内容传递给next()
function (except the string 'route'
or 'router'
), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.next()
函数(字符串'route'
或'router'
除外),Express会将当前请求视为错误,并将跳过任何剩余的非错误处理路由和中间件函数。
Because you have access to the request object, the response object, the next middleware function in the stack, and the whole Node.js API, the possibilities with middleware functions are endless.因为您可以访问请求对象、响应对象、堆栈中的下一个中间件函数以及整个Node.js API,所以中间件函数的可能性是无穷的。
For more information about Express middleware, see: Using Express middleware.有关Express中间件的更多信息,请参阅:使用Express中间件。
If you need your middleware to be configurable, export a function which accepts an options object or other parameters, which, then returns the middleware implementation based on the input parameters.如果需要配置中间件,请导出一个函数,该函数接受选项对象或其他参数,然后根据输入参数返回中间件实现。
File: 文件:my-middleware.js
module.exports = function (options) {
return function (req, res, next) {
// Implement the middleware function based on the options object
next()
}
}
The middleware can now be used as shown below.现在可以使用中间件,如下所示。
var mw = require('./my-middleware.js')
app.use(mw({ option1: '1', option2: '2' }))
Refer to cookie-session and compression for examples of configurable middleware.有关可配置中间件的示例,请参阅cookie会话和压缩。