Express是一个路由和中间件Web框架,其自身的功能很少:Express应用程序本质上是一系列中间件函数调用。
中间件功能是可以访问请求对象req),响应对象res)和应用程序的请求-响应周期中的下一个中间件功能的功能。下一个中间件功能通常由名为的变量表示next
中间件功能可以执行以下任务:

  • 执行任何代码。
  • 更改请求和响应对象。
  • 结束请求-响应周期。
  • 调用堆栈中的下一个中间件函数。

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

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

应用层中间件

使用和函数将应用程序级中间件绑定到应用程序对象的实例,其中,中间件函数以小写形式处理请求的HTTP方法(其中GET,PUT或POST)。app.use()``app.METHOD()``METHOD
此示例显示了没有安装路径的中间件功能。每次应用收到请求时,都会执行该功能。

  1. var express = require('express')
  2. var app = express()
  3. app.use(function (req, res, next) {
  4. console.log('Time:', Date.now())
  5. next()
  6. })

此示例显示了/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('请求URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('请求Type:', req.method)
  next()
})

路由处理程序使您可以为一个路径定义多个路由。下面的示例为到/user/:id路径的GET请求定义了两条路由。第二条路由不会引起任何问题,但是由于第一条路由将结束请求-响应周期,因此它将永远不会被调用。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id路径的GET请求。

app.get('/user/:id', function (req, res, next) {
  console.log('ID:', req.params.id)
  next()
}, function (req, res, next) {
  res.send('用户信息')
})
//  /user/:id 路径的处理(打印用户 ID)
app.get('/user/:id', function (req, res, next) {
  res.end(req.params.id)
})

要从路由器中间件堆栈中跳过其余中间件功能,请调用next('route')将控制权传递给下一条路由。 注意next('route')仅在使用app.METHOD()router.METHOD()函数加载的中间件函数中有效。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id路径的GET请求。

app.get('/user/:id', function (req, res, next) {
  // 如果用户 ID 是 0, 跳过进入下一个路由
  if (req.params.id === '0') next('route')
  // 否则传递控制到这个路由堆栈中的下一个中间件
  else next()
}, function (req, res, next) {
  // 发送‘regular’响应
  res.send('regular')
})
// /user/:id 路径的处理(发送special响应)
app.get('/user/:id', function (req, res, next) {
  res.send('special')
})

中间件也可以在数组中声明为可重用。
此示例显示了一个带有中间件子堆栈的数组,该子堆栈处理对/user/:id路径的GET请求

function logOriginalUrl (req, res, next) {
  console.log('请求URL:', req.originalUrl)
  next()
}
function logMethod (req, res, next) {
  console.log('请求Type:', req.method)
  next()
}
var logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, function (req, res, next) {
  res.send('用户信息')
})

路由器级中间件

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

var router = express.Router()

使用router.use()router.METHOD()函数加载路由器级中间件。
以下示例代码通过使用路由器级中间件来复制上面显示的用于应用程序级中间件的中间件系统:

var express = require('express')
var app = express()
var router = express.Router()
// 没有挂载路径的中间件. 这段代码将对任何的请求都执行
router.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})
// 展示对/user/:id 路径的任何HTTP类型的请求的请求信息的中间件
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()
})
// 对/user/:id 路径的GET请求的处理中间件
router.get('/user/:id', function (req, res, next) {
  // 如果用户 ID 是 0,跳到下一个路由
  if (req.params.id === '0') next('route')
  // 否则传递到这个路由堆栈中的下一个中间件处理
  else next()
}, function (req, res, next) {
  // 返回渲染过的regular页面
  res.render('regular')
})
// 对 /user/:id 路径的处理(返回渲染过的special页面)
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id)
  res.render('special')
})
// 挂载路由在app根路径上
app.use('/', router)

要跳过路由器的其余中间件功能,请调用next('router') 将控制权转回路由器实例。
此示例显示了一个中间件子堆栈,该子堆栈处理对/user/:id路径的GET请求。

var express = require('express')
var app = express()
var router = express.Router()
// 在需要的时候,使用判断来决定是否跳过该路由实例的剩余路由
router.use(function (req, res, next) {
  if (!req.headers['x-auth']) return next('router')
  next()
})
router.get('/user/:id', function (req, res) {
  res.send('hello, user!')
})
// 使用router, 任何跳过的路由都将返回状态 401 
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')
    // 加载 cookies转换中间件
    app.use(cookieParser())
    
    有关Express常用的第三方中间件功能的部分列表,请参阅:第三方中间件