5.x API

注意: 这是早期的 beta 文档,可能不完整并且仍在开发中。

express()

创建一个 Express 应用程序。 express() 函数是 express 模块导出的顶级函数。

const express = require('express')
const app = express()

Methods

express.json([options])

这是 Express 中内置的中间件函数。 它使用 JSON 有效负载解析传入请求,并且基于 body-parser

返回仅解析 JSON 并且仅查看 Content-Type 标头与 type 选项匹配的请求的中间件。 此解析器接受正文的任何​​ Unicode 编码,并支持 gzipdeflate 编码的自动膨胀。

包含解析数据的新 body 对象在中间件(即 req.body)之后填充到 request 对象上,如果没有要解析的主体、Content-Type 不匹配或发生错误,则填充一个空对象({})。

由于 req.body 的形状基于用户控制的输入,因此该对象中的所有属性和值都是不可信的,应该在信任之前进行验证。 例如,req.body.foo.toString() 可能以多种方式失败,例如 foo 可能不存在或可能不是字符串,toString 可能不是函数,而是字符串或其他用户输入。

下表描述了可选 options 对象的属性。

属性 描述 类型 默认
inflate 启用或禁用处理放气(压缩)的物体; 当禁用时,泄气的主体会被拒绝。 布尔值 true
limit 控制最大请求正文大小。 如果这是一个数字,则该值指定字节数; 如果是字符串,则将该值传递给bytes库进行解析。 混合 "100kb"
reviver reviver 选项作为第二个参数直接传递给 JSON.parse。 您可以找到有关此论点 在关于 JSON.parse 的 MDN 文档中 的更多信息。 函数 null
strict 启用或禁用仅接受数组和对象; 禁用时将接受 JSON.parse 接受的任何内容。 布尔值 true
type 这用于确定中间件将解析的媒体类型。 此选项可以是字符串、字符串数组或函数。 如果不是函数,则 type 选项直接传递给 type-is 库,它可以是扩展名(如 json)、mime 类型(如 application/json)或带有通配符的 mime 类型(如 */**/json)。 如果是函数,则 type 选项被称为 fn(req),如果请求返回真值,则解析请求。 混合 "application/json"
verify 此选项(如果提供)称为 verify(req, res, buf, encoding),其中 buf 是原始请求正文的 Bufferencoding 是请求的编码。 可以通过抛出错误来中止解析。 函数 undefined

express.static(root, [options])

这是 Express 中内置的中间件函数。 它提供静态文件,基于 serve-static

注意: 为获得最佳效果,使用反向代理 缓存以提高服务静态资产的性能。

root 参数指定提供静态资产的根目录。 该函数通过将 req.url 与提供的 root 目录组合来确定要服务的文件。 当找不到文件时,它不会发送 404 响应,而是调用 next() 以继续下一个中间件,从而允许堆叠和回退。

下表描述了 options 对象的属性。 另见 下面的例子

属性 描述 类型 默认
dotfiles 确定如何处理点文件(以点 “.” 开头的文件或目录)。

请参见下面的 dotfiles
字符串 “ignore”
etag 启用或禁用 etag 生成

注意: express.static 总是发送弱 ETag。
布尔值 true
extensions 设置文件扩展名后备: 如果找不到文件,请搜索具有指定扩展名的文件并提供第一个找到的文件。 例子: ['html', 'htm'] 混合 false
fallthrough 让客户端错误作为未处理的请求通过,否则转发客户端错误。

请参见下面的 fallthrough
布尔值 true
immutable Cache-Control 响应标头中启用或禁用 immutable 指令。 如果启用,还应指定 maxAge 选项以启用缓存。 immutable 指令将阻止受支持的客户端在 maxAge 选项的生命周期内发出条件请求以检查文件是否已更改。 布尔值 false
index 发送指定的目录索引文件。 设置为 false 以禁用目录索引。 混合 “index.html”
lastModified Last-Modified 标头设置为操作系统上文件的最后修改日期。 布尔值 true
maxAge 设置 Cache-Control 标头的 max-age 属性(以毫秒为单位)或 ms 格式 中的字符串。 数字 0
redirect 当路径名是目录时,重定向到尾随 “/”。 布尔值 true
setHeaders 用于设置 HTTP 标头以与文件一起服务的功能。

请参见下面的 setHeaders
函数  

有关详细信息,请参阅 在 Express 中提供静态文件。 和使用中间件 - 内置中间件

dotfiles

此选项的可能值为:

  • “allow” - 对点文件没有特殊处理。
  • “deny” - 拒绝对点文件的请求,以 403 响应,然后调用 next()
  • “ignore” - 就好像点文件不存在一样,用 404 响应,然后调用 next()
fallthrough

当此选项为 true 时,客户端错误(例如错误请求或对不存在文件的请求)将导致此中间件简单地调用 next() 以调用堆栈中的下一个中间件。 当为 false 时,这些错误(甚至是 404)将调用 next(err)

将此选项设置为 true,以便您可以将多个物理目录映射到同一个 Web 地址或路由以填充不存在的文件。

如果您已将此中间件安装在严格设计为单个文件系统目录的路径上,请使用 false,这允许短路 404 以减少开销。 这个中间件也会响应所有的方法。

setHeaders

对于此选项,指定一个函数来设置自定义响应标头。 对标头的更改必须同步发生。

该函数的签名是:

fn(res, path, stat)

参数:

  • res响应对象
  • path,正在发送的文件路径。
  • stat,正在发送的文件的 stat 对象。

Example of express.static

下面是一个将 express.static 中间件函数与精心设计的选项对象一起使用的示例:

const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders (res, path, stat) {
    res.set('x-timestamp', Date.now())
  }
}

app.use(express.static('public', options))

express.Router([options])

创建一个新的 router 对象。

const router = express.Router([options])

可选的 options 参数指定路由的行为。

属性 描述 默认 可用性
caseSensitive 启用区分大小写。 默认禁用,将 “/Foo” 和 “/foo” 视为相同。  
mergeParams 保留来自父路由的 req.params 值。 如果父项和子项的参数名称冲突,则子项的值优先。 false 4.5.0+
strict 启用严格路由。 默认情况下禁用,路由对 “/foo” 和 “/foo/” 的处理相同。  

您可以像应用程序一样将中间件和 HTTP 方法路由(例如 getputpost 等)添加到 router

有关详细信息,请参阅 路由

express.urlencoded([options])

这是 Express 中内置的中间件函数。 它使用 urlencoded 有效负载解析传入的请求,并且基于 body-parser

返回仅解析 urlencoded 正文并仅查看 Content-Type 标头与 type 选项匹配的请求的中间件。 此解析器仅接受正文的 UTF-8 编码,并支持 gzipdeflate 编码的自动膨胀。

包含解析数据的新 body 对象在中间件(即 req.body)之后填充到 request 对象上,如果没有要解析的主体、Content-Type 不匹配或发生错误,则填充一个空对象({})。 该对象将包含键值对,其中值可以是字符串或数组(当 extendedfalse 时)或任何类型(当 extendedtrue 时)。

由于 req.body 的形状基于用户控制的输入,因此该对象中的所有属性和值都是不可信的,应该在信任之前进行验证。 例如,req.body.foo.toString() 可能以多种方式失败,例如 foo 可能不存在或可能不是字符串,toString 可能不是函数,而是字符串或其他用户输入。

下表描述了可选 options 对象的属性。

属性 描述 类型 默认
extended 此选项允许在使用 querystring 库(当 false)或 qs 库(当 true)解析 URL 编码数据之间进行选择。 “extended” 语法允许将丰富的对象和数组编码为 URL 编码格式,从而提供类似 JSON 的 URL 编码体验。 欲了解更多信息,请 查看 qs 库 布尔值 false
inflate 启用或禁用处理放气(压缩)的物体; 当禁用时,泄气的主体会被拒绝。 布尔值 true
limit 控制最大请求正文大小。 如果这是一个数字,则该值指定字节数; 如果是字符串,则将该值传递给bytes库进行解析。 混合 "100kb"
parameterLimit 此选项控制 URL 编码数据中允许的最大参数数。 如果请求包含的参数多于该值,则会引发错误。 数字 1000
type 这用于确定中间件将解析的媒体类型。 此选项可以是字符串、字符串数组或函数。 如果不是函数,则 type 选项直接传递给 type-is 库,它可以是扩展名(如 urlencoded)、mime 类型(如 application/x-www-form-urlencoded)或带有通配符的 mime 类型(如 */x-www-form-urlencoded)。 如果是函数,则 type 选项被称为 fn(req),如果请求返回真值,则解析请求。 混合 "application/x-www-form-urlencoded"
verify 此选项(如果提供)称为 verify(req, res, buf, encoding),其中 buf 是原始请求正文的 Bufferencoding 是请求的编码。 可以通过抛出错误来中止解析。 函数 undefined

应用

app 对象通常表示 Express 应用程序。 通过调用 Express 模块导出的顶级 express() 函数来创建它:

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('hello world')
})

app.listen(3000)

app 对象具有用于

它还具有影响应用程序行为方式的设置(属性); 有关详细信息,请参阅 应用程序设置

Express 应用程序对象可以从 请求对象响应对象 分别称为 req.appres.app

Properties

app.locals

app.locals 对象的属性是应用程序中的局部变量,并且可以在使用 res.render 呈现的模板中使用。

console.dir(app.locals.title)
// => 'My App'

console.dir(app.locals.email)
// => 'me@myapp.com'

设置后,app.locals 属性的值将在应用程序的整个生命周期中保持不变,而 res.locals 属性仅在请求的生命周期内有效。

您可以访问应用程序中呈现的模板中的局部变量。 这对于为模板以及应用程序级数据提供帮助函数很有用。 局部变量可通过 req.app.locals 在中间件中使用(参见 req.app

app.locals.title = 'My App'
app.locals.strftime = require('strftime')
app.locals.email = 'me@myapp.com'

app.mountpath

app.mountpath 属性包含一个或多个安装子应用程序的路径模式。

子应用程序是 express 的一个实例,可用于处理对路由的请求。

const express = require('express')

const app = express() // the main app
const admin = express() // the sub app

admin.get('/', (req, res) => {
  console.log(admin.mountpath) // /admin
  res.send('Admin Homepage')
})

app.use('/admin', admin) // mount the sub app

它类似于 req 对象的 baseUrl 属性,除了 req.baseUrl 返回匹配的 URL 路径,而不是匹配的模式。

如果子应用挂载在多个路径模式上,app.mountpath 返回其挂载的模式列表,如下例所示。

const admin = express()

admin.get('/', (req, res) => {
  console.log(admin.mountpath) // [ '/adm*n', '/manager' ]
  res.send('Admin Homepage')
})

const secret = express()
secret.get('/', (req, res) => {
  console.log(secret.mountpath) // /secr*t
  res.send('Admin Secret')
})

admin.use('/secr*t', secret) // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin) // load the 'admin' router on '/adm*n' and '/manager', on the parent app

app.router

应用程序的内置路由实例。 这是在第一次访问时懒惰地创建的。

const express = require('express')
const app = express()
const router = app.router

router.get('/', (req, res) => {
  res.send('hello world')
})

app.listen(3000)

您可以像应用程序一样向 router 添加中间件和 HTTP 方法路由。

有关详细信息,请参阅 路由

Events

app.on('mount', callback(parent))

当子应用安装在父应用上时,mount 事件会在子应用上触发。 父应用程序被传递给回调函数。

注意

子应用程序将:

  • 不继承具有默认值的设置值。 您必须在子应用程序中设置该值。
  • 继承设置的值,没有默认值。

详见 应用程序设置

const admin = express()

admin.on('mount', (parent) => {
  console.log('Admin Mounted')
  console.log(parent) // refers to the parent app
})

admin.get('/', (req, res) => {
  res.send('Admin Homepage')
})

app.use('/admin', admin)

Methods

app.all(path, callback [, callback ...])

此方法类似于标准 app.METHOD() 方法,不同之处在于它匹配所有 HTTP 动词。

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

示例

无论使用 GET、POST、PUT、DELETE 还是任何其他 HTTP 请求方法,对 /secret 的请求都会执行以下回调:

app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

app.all() 方法对于为特定路径前缀或任意匹配映射 “global” 逻辑很有用。 例如,如果您将以下内容放在所有其他路由定义的顶部,则要求从该点开始的所有路由都需要身份验证,并自动加载用户。 请记住,这些回调不必充当端点: loadUser可以执行一个任务,然后调用next()继续匹配后续路由。

app.all('*', requireAuthentication, loadUser)

或等价物:

app.all('*', requireAuthentication)
app.all('*', loadUser)

另一个示例是列入白名单的 “global” 功能。 该示例与上面的示例类似,但它仅限制以 “/api” 开头的路径:

app.all('/api/*', requireAuthentication)

app.delete(path, callback [, callback ...])

使用指定的回调函数将 HTTP DELETE 请求路由到指定路径。 有关详细信息,请参阅 路由指南

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

示例

app.delete('/', (req, res) => {
  res.send('DELETE request to homepage')
})

app.disable(name)

将布尔设置 name 设置为 false,其中 name应用设置表 的属性之一。 为布尔属性调用 app.set('foo', false) 与调用 app.disable('foo') 相同。

例如:

app.disable('trust proxy')
app.get('trust proxy')
// => false

app.disabled(name)

如果禁用布尔设置 name (false),则返回 true,其中 name应用设置表 的属性之一。

app.disabled('trust proxy')
// => true

app.enable('trust proxy')
app.disabled('trust proxy')
// => false

app.enable(name)

将布尔设置 name 设置为 true,其中 name应用设置表 的属性之一。 为布尔属性调用 app.set('foo', true) 与调用 app.enable('foo') 相同。

app.enable('trust proxy')
app.get('trust proxy')
// => true

app.enabled(name)

如果启用了设置 name (true),则返回 true,其中 name应用设置表 的属性之一。

app.enabled('trust proxy')
// => false

app.enable('trust proxy')
app.enabled('trust proxy')
// => true

app.engine(ext, callback)

将给定的模板引擎 callback 注册为 ext

默认情况下,Express 会根据文件扩展名 require() 引擎。 例如,如果您尝试渲染 “foo.pug” 文件,Express 会在内部调用以下内容,并在后续调用中缓存 require() 以提高性能。

app.engine('pug', require('pug').__express)

对于不提供开箱即用的 .__express 的引擎,或者如果您希望 “map” 为模板引擎提供不同的扩展,请使用此方法。

例如,要将 EJS 模板引擎映射到 “.html” 文件:

app.engine('html', require('ejs').renderFile)

在这种情况下,EJS 提供了一个 .renderFile() 方法,其签名与 Express 所期望的相同: (path, options, callback),但请注意,它在内部将此方法别名为 ejs.__express,因此如果您使用 “.ejs” 扩展,则无需执行任何操作。

一些模板引擎不遵循这个约定。 consolidate.js 库映射 Node 模板引擎以遵循此约定,因此它们可以与 Express 无缝协作。

const engines = require('consolidate')
app.engine('haml', engines.haml)
app.engine('html', engines.hogan)

app.get(name)

返回 name 应用设置的值,其中 name应用设置表 中的字符串之一。 例如:

app.get('title')
// => undefined

app.set('title', 'My Site')
app.get('title')
// => "My Site"

app.get(path, callback [, callback ...])

使用指定的回调函数将 HTTP GET 请求路由到指定路径。

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

有关详细信息,请参阅 路由指南

示例

app.get('/', (req, res) => {
  res.send('GET request to homepage')
})

app.listen(path, [callback])

启动一个 UNIX 套接字并监听给定路径上的连接。 此方法与 Node 的 http.Server.listen() 相同。

const express = require('express')
const app = express()
app.listen('/tmp/sock')

app.listen([port[, host[, backlog]]][, callback])

绑定并监听指定主机和端口上的连接。 此方法与 Node 的 http.Server.listen() 相同。

如果端口被省略或为 0,操作系统将分配一个任意未使用的端口,这对于自动化任务(测试等)等情况很有用。

const express = require('express')
const app = express()
app.listen(3000)

express() 返回的 app 实际上是一个 JavaScript Function,旨在作为回调传递给 Node 的 HTTP 服务器来处理请求。 这使得为​​您的应用程序的 HTTP 和 HTTPS 版本提供相同的代码库变得很容易,因为应用程序不会从这些版本继承(它只是一个回调):

const express = require('express')
const https = require('https')
const http = require('http')
const app = express()

http.createServer(app).listen(80)
https.createServer(options, app).listen(443)

app.listen() 方法返回一个 http.Server 对象,并且(对于 HTTP)是以下的便捷方法:

app.listen = function () {
  const server = http.createServer(this)
  return server.listen.apply(server, arguments)
}

注意: Node 的 http.Server.listen() 方法的所有形式其实都是支持的。

app.METHOD(path, callback [, callback ...])

路由 HTTP 请求,其中 METHOD 是请求的 HTTP 方法,如 GET、PUT、POST 等,小写。 因此,实际的方法是 app.get()app.post()app.put() 等等。 有关完整列表,请参见下面的 路由方法

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

路由方法

Express 支持以下与 HTTP 同名方法对应的路由方法:

  • checkout
  • copy
  • delete
  • get
  • head
  • lock
  • merge
  • mkactivity
  • mkcol
  • move
  • m-search
  • notify
  • options
  • patch
  • post
  • purge
  • put
  • report
  • search
  • subscribe
  • trace
  • unlock
  • unsubscribe

API 文档仅针对最流行的 HTTP 方法 app.get()app.post()app.put()app.delete() 有明确的条目。 但是,上面列出的其他方法的工作方式完全相同。

要路由转换为无效 JavaScript 变量名的方法,请使用方括号表示法。 例如,app['m-search']('/', function ...

如果 app.get() 之前的路径没有调用 app.head(),则除了 GET 方法之外,还会为 HTTP HEAD 方法自动调用 app.get() 函数。

方法 app.all() 不是从任何 HTTP 方法派生的,而是在指定路径为所有 HTTP 请求方法加载中间件。 有关详细信息,请参阅 app.all

有关路由的更多信息,请参阅 路由指南

app.param(name, callback)

路由参数添加回调触发器,其中name为参数名称或参数数组,callback为回调函数。 回调函数的参数依次是请求对象、响应对象、下一个中间件、参数的值和参数的名称。

如果 name 是一个数组,则为其中声明的每个参数注册 callback 触发器,按照它们的声明顺序。 此外,对于除最后一个之外的每个声明的参数,在回调中调用 next 将为下一个声明的参数调用回调。 对于最后一个参数,对 next 的调用将调用当前正在处理的路由的下一个中间件,就像 name 只是一个字符串一样。

例如,当 :user 出现在路由路径中时,您可以映射用户加载逻辑以自动将 req.user 提供给路由,或对参数输入执行验证。

app.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})

参数回调函数在定义它们的路由上是本地的。 它们不会被安装的应用程序或路由继承。 因此,在 app 上定义的参数回调将仅由在 app 路由上定义的路由参数触发。

所有参数回调将在参数出现的任何路由的任何处理程序之前调用,并且它们在请求-响应周期中仅被调用一次,即使参数在多个路由中匹配,如下例所示。

app.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE')
  next()
})

app.get('/user/:id', (req, res, next) => {
  console.log('although this matches')
  next()
})

app.get('/user/:id', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42 上,打印以下内容:

CALLED ONLY ONCE
although this matches
and this matches too
app.param(['id', 'page'], (req, res, next, value) => {
  console.log('CALLED ONLY ONCE with', value)
  next()
})

app.get('/user/:id/:page', (req, res, next) => {
  console.log('although this matches')
  next()
})

app.get('/user/:id/:page', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42/3 上,打印以下内容:

CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this matches too

app.path()

返回应用程序的规范路径,一个字符串。

const app = express()
const blog = express()
const blogAdmin = express()

app.use('/blog', blog)
blog.use('/admin', blogAdmin)

console.log(app.path()) // ''
console.log(blog.path()) // '/blog'
console.log(blogAdmin.path()) // '/blog/admin'

在安装应用程序的复杂情况下,此方法的行为可能会变得非常复杂: 通常最好使用 req.baseUrl 来获取应用程序的规范路径。

app.post(path, callback [, callback ...])

使用指定的回调函数将 HTTP POST 请求路由到指定路径。 有关详细信息,请参阅 路由指南

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

示例

app.post('/', (req, res) => {
  res.send('POST request to homepage')
})

app.put(path, callback [, callback ...])

使用指定的回调函数将 HTTP PUT 请求路由到指定路径。

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

示例

app.put('/', (req, res) => {
  res.send('PUT request to homepage')
})

app.render(view, [locals], callback)

通过 callback 函数返回视图的呈现 HTML。 它接受一个可选参数,该参数是一个包含视图局部变量的对象。 它和 res.render() 一样,只是它不能自己将渲染视图发送给客户端。

app.render() 视为生成渲染视图字符串的实用函数。 res.render() 在内部使用 app.render() 来渲染视图。

局部变量 cache 保留用于启用视图缓存。 设置为true,如果你想在开发过程中缓存视图; 默认情况下在生产中启用视图缓存。

app.render('email', (err, html) => {
  // ...
})

app.render('email', { name: 'Tobi' }, (err, html) => {
  // ...
})

app.route(path)

返回单个路由的实例,然后您可以使用它来处理带有可选中间件的 HTTP 动词。 使用 app.route() 来避免重复的路由名称(从而避免拼写错误)。

const app = express()

app.route('/events')
  .all((req, res, next) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get((req, res, next) => {
    res.json({})
  })
  .post((req, res, next) => {
    // maybe add a new event...
  })

app.set(name, value)

将设置 name 分配给 value。 您可以存储任何您想要的值,但某些名称可用于配置服务器的行为。 这些特殊名称列在 应用设置表 中。

为布尔属性调用 app.set('foo', true) 与调用 app.enable('foo') 相同。 同样,为布尔属性调用 app.set('foo', false) 与调用 app.disable('foo') 相同。

使用 app.get() 检索设置的值。

app.set('title', 'My Site')
app.get('title') // "My Site"

Application Settings

下表列出了应用程序设置。

请注意,子应用程序将:

  • 不继承具有默认值的设置值。 您必须在子应用程序中设置该值。
  • 继承没有默认值的设置值; 下表明确指出了这些。

例外: 子应用程序将继承 trust proxy 的值,即使它具有默认值(为了向后兼容); 子应用在生产环境中不会继承 view cache 的值(当 NODE_ENV 为 “production” 时)。

属性类型描述默认

case sensitive routing

布尔值

启用区分大小写。 启用后,"/Foo" 和 "/foo" 是不同的路由。 禁用时,"/Foo" 和 "/foo" 被视为相同。

注意: 子应用将继承此设置的值。

N/A (undefined)

env

字符串 环境模式。 生产环境一定要设置为"production"; 见 Production best practices: performance and reliability

process.env.NODE_ENVNODE_ENV 环境变量)或 “development”(如果未设置 NODE_ENV)。

etag

多变

设置 ETag 响应标头。 有关可能的值,请参阅 etag 选项表

有关 HTTP ETag 标头的更多信息

weak

jsonp callback name

字符串 指定默认 JSONP 回调名称。

“callback”

json escape

布尔值

启用从 res.jsonres.jsonpres.send API 转义 JSON 响应。 这会将字符 <>& 转义为 JSON 中的 Unicode 转义序列。 这样做的目的是在客户端嗅探 HTML 响应时协助 缓解某些类型的持续性 XSS 攻击

注意: 子应用将继承此设置的值。

N/A (undefined)

json replacer

多变 'replacer' argument used by `JSON.stringify`

注意: 子应用将继承此设置的值。

N/A (undefined)

json spaces

多变 'space' argument used by `JSON.stringify`。 这通常设置为用于缩进美化 JSON 的空格数。

注意: 子应用将继承此设置的值。

N/A (undefined)

query parser

多变

通过将值设置为 false 来禁用查询解析,或者将查询解析器设置为使用 “simple” 或 “extended” 或自定义查询字符串解析函数。

简单查询解析器基于 Node 的原生查询解析器 querystring

扩展查询解析器基于 qs

自定义查询字符串解析函数将接收完整的查询字符串,并且必须返回查询键及其值的对象。

"extended"

strict routing

布尔值

启用严格路由。 启用后,路由将 "/foo" 和 "/foo/" 视为不同。 否则,路由将 "/foo" 和 "/foo/" 视为相同。

注意: 子应用将继承此设置的值。

N/A (undefined)

subdomain offset

数字 要删除以访问子域的主机的点分隔部分的数量。 2

trust proxy

多变

指示应用程序位于前端代理之后,并使用 X-Forwarded-* 标头来确定客户端的连接和 IP 地址。 注意: X-Forwarded-* 标头很容易被欺骗,检测到的 IP 地址也不可靠。

启用后,Express 会尝试确定通过前端代理或一系列代理连接的客户端的 IP 地址。 `req.ips` 属性,然后包含客户端连接通过的 IP 地址数组。 要启用它,请使用 trust proxy options table 中描述的值。

`trust proxy` 设置是使用 proxy-addr 包实现的。 有关更多信息,请参阅其文档。

注意: 子应用将要 继承此设置的值,即使它具有默认值。

false (禁用)

views

字符串或数组 应用程序视图的目录或目录数组。 如果是数组,则按照它们在数组中出现的顺序查找视图。

process.cwd() + '/views'

view cache

布尔值

启用视图模板编译缓存。

注意: 子应用在生产中不会继承此设置的值(当 `NODE_ENV` 为 "production" 时)。

true 在生产中,否则未定义。

view engine

字符串 省略时使用的默认引擎扩展。

注意: 子应用将继承此设置的值。

N/A (undefined)

x-powered-by

布尔值 启用 "X-Powered-By: Express" HTTP 标头。

true

Options for `trust proxy` setting

阅读 代理背后的 Express 了解更多信息。

类型
布尔值

如果是 true,则客户端的 IP 地址被理解为 X-Forwarded-* 标头中最左边的条目。

如果是false,则应用理解为直接面向互联网,客户端的IP地址来源于req.connection.remoteAddress。 这是默认设置。

字符串
包含逗号分隔值的字符串
字符串数组

要信任的 IP 地址、子网或 IP 地址数组和子网。 预配置的子网名称为:

  • loopback - 127.0.0.1/8::1/128
  • linklocal - 169.254.0.0/16fe80::/10
  • uniquelocal - 10.0.0.0/8172.16.0.0/12192.168.0.0/16fc00::/7

通过以下任一方式设置 IP 地址:

指定单个子网:

app.set('trust proxy', 'loopback')

指定子网和地址:

app.set('trust proxy', 'loopback, 123.123.123.123')

将多个子网指定为 CSV:

app.set('trust proxy', 'loopback, linklocal, uniquelocal')

将多个子网指定为数组:

app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal'])

指定时,IP 地址或子网将被排除在地址确定过程之外,并将离应用服务器最近的不受信任的 IP 地址确定为客户端的 IP 地址。

数字

相信nth 作为客户端从前置代理服务器跳转。

函数

自定义信任实现。 仅当您知道自己在做什么时才使用它。

app.set('trust proxy', (ip) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123') return true // trusted IPs
  else return false
})
Options for `etag` setting

注意: 这些设置仅适用于动态文件,不适用于静态文件。 express.static 中间件会忽略这些设置。

ETag 功能是使用 etag 包实现的。 有关更多信息,请参阅其文档。

类型
布尔值

true 启用弱 ETag。 这是默认设置。
false 完全禁用 ETag。

字符串 如果 "strong",启用强 ETag。
如果 "weak",启用弱 ETag。
函数

自定义 ETag 函数实现。 仅当您知道自己在做什么时才使用它。

app.set('etag', (body, encoding) => {
  return generateHash(body, encoding) // consider the function is defined
})

app.use([path,] callback [, callback...])

在指定路径挂载指定的 中间件 函数: 当请求路径的基匹配 path 时执行中间件函数。

参数

参数 描述 默认
path 调用中间件函数的路径; 可以是以下任何一项:
  • 表示路径的字符串。
  • 路径模式。
  • 匹配路径的正则表达式模式。
  • 以上任何一种组合的数组。
例如,参见 Path examples
'/'(根路径)
callback 回调函数; 可:
  • 一个中间件函数。
  • 一系列中间件函数(以逗号分隔)。
  • 一组中间件函数。
  • 以上所有的组合。

您可以提供多个回调函数,其行为类似于中间件,只是这些回调可以调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由施加先决条件,然后如果没有理由继续当前路由,则将控制权传递给后续路由。

当回调函数抛出错误或返回被拒绝的 Promise 时,`next(err)` 将被自动调用。

由于 routerapp 实现了中间件接口,您可以像使用任何其他中间件函数一样使用它们。

例如,参见 Middleware callback function examples

描述

路由将匹配紧随其路径的任何路径,并带有 “/“。 例如: app.use('/apple', ...) 将匹配 “/apple”、”/apple/images”、”/apple/images/news” 等。

由于 path 默认为 “/”,因此对于应用程序的每个请求,都会执行没有路径挂载的中间件。
例如,这个中间件函数将为应用程序的每个请求执行:

app.use((req, res, next) => {
  console.log('Time: %d', Date.now())
  next()
})

注意

子应用程序将:

  • 不继承具有默认值的设置值。 您必须在子应用程序中设置该值。
  • 继承设置的值,没有默认值。

详见 应用程序设置

中间件函数是按顺序执行的,因此中间件包含的顺序很重要。

// this middleware will not allow the request to go beyond it
app.use((req, res, next) => {
  res.send('Hello World')
})

// requests will never reach this route
app.get('/', (req, res) => {
  res.send('Welcome')
})

错误处理中间件

错误处理中间件总是需要四个参数。 您必须提供四个参数以将其标识为错误处理中间件函数。 即使您不需要使用 next 对象,您也必须指定它来维护签名。 否则,next 对象将被解释为常规中间件,无法处理错误。 有关错误处理中间件的详细信息,请参见: 错误处理

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

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

路径示例

下表提供了一些用于挂载中间件的有效 path 值的简单示例。

类型 例子
路径

这将匹配以 /abcd 开头的路径:

app.use('/abcd', (req, res, next) => {
  next()
})
路径模式

这将匹配以 /abcd/abd 开头的路径:

app.use('/ab(c?)d', (req, res, next) => {
  next()
})
正则表达式

这将匹配以 /abc/xyz 开头的路径:

app.use(/\/abc|\/xyz/, (req, res, next) => {
  next()
})
数组

这将匹配以 /abcd/xyza/lmn/pqr 开头的路径:

app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], (req, res, next) => {
  next()
})

中间件回调函数示例

下表提供了可用作 app.use()app.METHOD()app.all()callback 参数的中间件函数的一些简单示例。 尽管这些示例适用于 app.use(),但它们也适用于 app.use()app.METHOD()app.all()

用法 例子
单一中间件

您可以在本地定义和挂载中间件函数。

app.use((req, res, next) => {
  next()
})

路由是有效的中间件。

const router = express.Router()
router.get('/', (req, res, next) => {
  next()
})
app.use(router)

Express 应用程序是有效的中间件。 js const subApp = express() subApp.get('/', (req, res, next) => { next() }) app.use(subApp)

系列中间件

您可以在同一挂载路径中指定多个中间件函数。

const r1 = express.Router()
r1.get('/', (req, res, next) => {
  next()
})

const r2 = express.Router()
r2.get('/', (req, res, next) => {
  next()
})

app.use(r1, r2)
数组

使用数组对中间件进行逻辑分组。

const r1 = express.Router()
r1.get('/', (req, res, next) => {
  next()
})

const r2 = express.Router()
r2.get('/', (req, res, next) => {
  next()
})

app.use([r1, r2])
组合

您可以结合上述所有挂载中间件的方式。

function mw1 (req, res, next) { next() }
function mw2 (req, res, next) { next() }

const r1 = express.Router()
r1.get('/', (req, res, next) => { next() })

const r2 = express.Router()
r2.get('/', (req, res, next) => { next() })

const subApp = express()
subApp.get('/', (req, res, next) => { next() })

app.use(mw1, [mw2, r1, r2], subApp)

以下是在 Express 应用程序中使用 express.static 中间件的一些示例。

从应用程序目录中的 “public” 目录为应用程序提供静态内容:

// GET /style.css etc
app.use(express.static(path.join(__dirname, 'public')))

仅当请求路径以 “/static” 为前缀时,将中间件安装在 “/static” 以提供静态内容:

// GET /static/style.css etc.
app.use('/static', express.static(path.join(__dirname, 'public')))

通过在静态中间件之后加载记录器中间件来禁用静态内容请求的日志记录:

app.use(express.static(path.join(__dirname, 'public')))
app.use(logger())

提供来自多个目录的静态文件,但 “./public” 优先于其他目录:

app.use(express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'files')))
app.use(express.static(path.join(__dirname, 'uploads')))

请求

req 对象表示 HTTP 请求,并具有请求查询字符串、参数、正文、HTTP 标头等的属性。 在本文档中,按照惯例,该对象始终称为 req(HTTP 响应为 res),但其实际名称由您正在使用的回调函数的参数确定。

例如:

app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`)
})

但你也可以拥有:

app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`)
})

req对象是Node自带请求对象的增强版,支持所有内置字段和方法

Properties

在 Express 4 中,默认情况下 req.filesreq 对象上不再可用。 要访问 req.files 对象上的上传文件,请使用多部分处理中间件,如 busboymulterformidablemultipartyconnect-multipartypez

req.app

此属性包含对使用中间件的 Express 应用程序实例的引用。

如果您遵循创建一个模块的模式,该模块仅导出一个中间件函数并在主文件中 require(),则中间件可以通过 req.app 访问 Express 实例

例如:

// index.js
app.get('/viewdirectory', require('./mymiddleware.js'))
// mymiddleware.js
module.exports = (req, res) => {
  res.send(`The views directory is ${req.app.get('views')}`)
}

req.baseUrl

安装路由实例的 URL 路径。

req.baseUrl 属性类似于 app 对象的 mountpath 属性,除了 app.mountpath 返回匹配的路径模式。

例如:

const greet = express.Router()

greet.get('/jp', (req, res) => {
  console.log(req.baseUrl) // /greet
  res.send('Konichiwa!')
})

app.use('/greet', greet) // load the router on '/greet'

即使您使用路径模式或一组路径模式来加载路由,baseUrl 属性也会返回匹配的字符串,而不是模式。 在以下示例中,greet 路由加载在两个路径模式上。

app.use(['/gre+t', '/hel{2}o'], greet) // load the router on '/gre+t' and '/hel{2}o'

当向 /greet/jp 发出请求时,req.baseUrl 是 “/greet”。 当向 /hello/jp 发出请求时,req.baseUrl 是 “/hello”。

req.body

包含在请求正文中提交的数据键值对。 默认情况下,它是 undefined,并在您使用 body-parsermulter 等正文解析中间件时填充。

由于 req.body 的形状基于用户控制的输入,因此该对象中的所有属性和值都是不可信的,应该在信任之前进行验证。 例如,req.body.foo.toString() 可能以多种方式失败,例如 foo 可能不存在或可能不是字符串,toString 可能不是函数,而是字符串或其他用户输入。

以下示例显示如何使用正文解析中间件填充 req.body

const app = require('express')()
const bodyParser = require('body-parser')
const multer = require('multer') // v1.0.5
const upload = multer() // for parsing multipart/form-data

app.use(bodyParser.json()) // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded

app.post('/profile', upload.array(), (req, res, next) => {
  console.log(req.body)
  res.json(req.body)
})

req.cookies

使用 cookie-parser 中间件时,该属性是一个包含请求发送的 cookie 的对象。 如果请求不包含 cookie,则默认为 {}

// Cookie: name=tj
console.dir(req.cookies.name)
// => "tj"

如果 cookie 已签名,则必须使用 req.signedCookies

有关更多信息、问题或疑虑,请参阅 cookie-parser

req.fresh

当响应在客户端的缓存中仍然是 “fresh” 时,返回 true,否则返回 false,表示客户端缓存现在已经过时,应该发送完整的响应。

当客户端发送 Cache-Control: no-cache 请求头指示端到端的重新加载请求时,该模块将返回 false 以使处理这些请求透明。

有关缓存验证如何工作的更多详细信息,请参阅 HTTP/1.1 缓存规范

console.dir(req.fresh)
// => true

req.host

包含从 Host HTTP 标头派生的主机。

trust proxy 设置 不计算为 false 时,此属性将改为从 X-Forwarded-Host 标头字段中获取值。 此标头可以由客户端或代理设置。

如果请求中有多个 X-Forwarded-Host 标头,则使用第一个标头的值。 这包括一个带有逗号分隔值的标头,其中使用了第一个值。

// Host: "example.com:3000"
console.dir(req.host)
// => 'example.com:3000'

// Host: "[::1]:3000"
console.dir(req.host)
// => '[::1]:3000'

req.hostname

包含从 Host HTTP 标头派生的主机名。

trust proxy 设置 不计算为 false 时,此属性将改为从 X-Forwarded-Host 标头字段中获取值。 此标头可以由客户端或代理设置。

如果请求中有多个 X-Forwarded-Host 标头,则使用第一个标头的值。 这包括一个带有逗号分隔值的标头,其中使用了第一个值。

在 Express v4.17.0 之前,X-Forwarded-Host 不能包含多个值或多次出现。

// Host: "example.com:3000"
console.dir(req.hostname)
// => 'example.com'

req.ip

包含请求的远程 IP 地址。

trust proxy 设置 不计算为 false 时,此属性的值派生自 X-Forwarded-For 标头中最左侧的条目。 此标头可以由客户端或代理设置。

console.dir(req.ip)
// => "127.0.0.1"

req.ips

trust proxy 设置 不评估为 false 时,此属性包含 X-Forwarded-For 请求标头中指定的 IP 地址数组。 否则,它包含一个空数组。 此标头可以由客户端或代理设置。

例如,如果 X-Forwarded-Forclient, proxy1, proxy2,则 req.ips 将是 ["client", "proxy1", "proxy2"],其中 proxy2 是最下游的。

req.method

包含与请求的 HTTP 方法对应的字符串: GETPOSTPUT 等等。

req.originalUrl

req.url 不是原生的 Express 属性,它继承自 Node 的 http 模块

这个属性很像 req.url; 但是,它保留了原始请求 URL,允许您出于内部路由目的自由重写 req.url。 例如,app.use() 的 “mounting” 特性将重写 req.url 以剥离挂载点。

// GET /search?q=something
console.dir(req.originalUrl)
// => "/search?q=something"

req.originalUrl 在中间件和路由对象中都可用,并且是 req.baseUrlreq.url 的组合。 考虑以下示例:

// GET 'http://www.example.com/admin/new?sort=desc'
app.use('/admin', (req, res, next) => {
  console.dir(req.originalUrl) // '/admin/new?sort=desc'
  console.dir(req.baseUrl) // '/admin'
  console.dir(req.path) // '/new'
  next()
})

req.params

此属性是一个包含映射到 命名路由 “parameters” 的属性的对象。 例如,如果您有路由 /user/:name,则 “name” 属性可用作 req.params.name。 此对象默认为 {}

// GET /user/tj
console.dir(req.params.name)
// => "tj"

当您为路由定义使用正则表达式时,捕获组在数组中使用 req.params[n] 提供,其中 n 是 nth 捕获组。 此规则适用于带有字符串路由的未命名通配符匹配,例如 /file/*

// GET /file/javascripts/jquery.js
console.dir(req.params[0])
// => "javascripts/jquery.js"

如果您需要更改 req.params 中的键,请使用 app.param 处理程序。 更改仅适用于已在路由路径中定义的 参数

在中间件或路由处理程序中对 req.params 对象所做的任何更改都将被重置。

注意: Express 自动解码 req.params 中的值(使用 decodeURIComponent)。

req.path

包含请求 URL 的路径部分。

// example.com/users?sort=desc
console.dir(req.path)
// => "/users"

从中间件调用时,挂载点不包含在 req.path 中。 有关详细信息,请参阅 app.use()

req.protocol

包含请求协议字符串: http 或(对于 TLS 请求)https

trust proxy 设置 不计算为 false 时,此属性将使用 X-Forwarded-Proto 标头字段的值(如果存在)。 此标头可以由客户端或代理设置。

console.dir(req.protocol)
// => "http"

req.query

此属性是一个对象,其中包含路由中每个查询字符串参数的属性。 当 查询解析器 设置为禁用时,它是一个空对象 {},否则它是配置的查询解析器的结果。

由于 req.query 的形状基于用户控制的输入,因此该对象中的所有属性和值都是不可信的,应该在信任之前进行验证。 例如,req.query.foo.toString() 可能以多种方式失败,例如 foo 可能不存在或可能不是字符串,toString 可能不是函数,而是字符串或其他用户输入。

可以使用 查询解析器应用设置 配置此属性的值,以按照您的应用程序需要的方式工作。 一个非常流行的查询字符串解析器是 qs 模块,这是默认使用的。 qs 模块可以通过许多设置进行配置,并且可能需要使用与默认设置不同的设置来填充 req.query

const qs = require('qs')
app.setting('query parser',
  (str) => qs.parse(str, { /* custom options */ }))

查看 查询解析器应用设置 文档以了解其他自定义选项。

req.res

此属性包含对与此请求对象相关的 response object 的引用。

req.route

包含当前匹配的路由,一个字符串。 例如:

app.get('/user/:id?', (req, res) => {
  console.log(req.route)
  res.send('GET')
})

上一个片段的示例输出:

{ path: '/user/:id?',
  stack:
   [ { handle: [Function: userIdHandler],
       name: 'userIdHandler',
       params: undefined,
       path: undefined,
       keys: [],
       regexp: /^\/?$/i,
       method: 'get' } ],
  methods: { get: true } }

req.secure

如果建立了 TLS 连接,则为 true 的布尔属性。 相当于以下内容:

req.protocol === 'https'

req.signedCookies

使用 cookie-parser 中间件时,此属性包含请求发送的已签名 cookie,未签名且可供使用。 签名的 cookie 驻留在不同的对象中以显示开发人员的意图; 否则,可能会对 req.cookie 值(很容易欺骗)进行恶意攻击。 请注意,签署 cookie 不会使其成为 “hidden” 或加密; 但只是防止篡改(因为用于签名的秘密是私有的)。

如果未发送签名 cookie,则该属性默认为 {}

// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user)
// => "tobi"

有关更多信息、问题或疑虑,请参阅 cookie-parser

req.stale

表示请求是否为”stale,”,与req.fresh相反。 有关详细信息,请参阅 req.fresh

console.dir(req.stale)
// => true

req.subdomains

请求域名中的子域数组。

// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains)
// => ["ferrets", "tobi"]

应用程序属性 subdomain offset,默认为 2,用于确定子域段的开始。 要更改此行为,请使用 app.set 更改其值。

req.xhr

如果请求的 X-Requested-With 标头字段为 “XMLHttpRequest”,则为 true 的布尔属性,表示该请求是由 jQuery 等客户端库发出的。

console.dir(req.xhr)
// => true

Methods

req.accepts(types)

根据请求的 Accept HTTP 标头字段检查指定的内容类型是否可接受。 该方法返回最佳匹配,或者如果指定的内容类型都不可接受,则返回 false(在这种情况下,应用程序应以 406 "Not Acceptable" 响应)。

type 值可以是单个 MIME 类型字符串(例如 “application/json”)、扩展名(例如 “json”)、逗号分隔的列表或数组。 对于列表或数组,该方法返回最佳匹配(如果有)。

// Accept: text/html
req.accepts('html')
// => "html"

// Accept: text/*, application/json
req.accepts('html')
// => "html"
req.accepts('text/html')
// => "text/html"
req.accepts(['json', 'text'])
// => "json"
req.accepts('application/json')
// => "application/json"

// Accept: text/*, application/json
req.accepts('image/png')
req.accepts('png')
// => false

// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json'])
// => "json"

如需更多信息,或者如果您有问题或疑虑,请参阅 accepts

req.acceptsCharsets(charset [, ...])

根据请求的 Accept-Charset HTTP 标头字段,返回指定字符集的第一个接受的字符集。 如果不接受任何指定的字符集,则返回 false

如需更多信息,或者如果您有问题或疑虑,请参阅 accepts

req.acceptsEncodings(encoding [, ...])

根据请求的 Accept-Encoding HTTP 标头字段,返回指定编码的第一个接受的编码。 如果不接受任何指定的编码,则返回 false

如需更多信息,或者如果您有问题或疑虑,请参阅 accepts

req.acceptsLanguages(lang [, ...])

根据请求的 Accept-Language HTTP 标头字段,返回指定语言中第一个接受的语言。 如果不接受任何指定的语言,则返回 false

如需更多信息,或者如果您有问题或疑虑,请参阅 accepts

req.get(field)

返回指定的 HTTP 请求头字段(不区分大小写的匹配)。 ReferrerReferer 字段可以互换。

req.get('Content-Type')
// => "text/plain"

req.get('content-type')
// => "text/plain"

req.get('Something')
// => undefined

别名为 req.header(field)

req.is(type)

如果传入请求的 “Content-Type” HTTP 标头字段与 type 参数指定的 MIME 类型匹配,则返回匹配的内容类型。 如果请求没有正文,则返回 null。 否则返回 false

// With Content-Type: text/html; charset=utf-8
req.is('html') // => 'html'
req.is('text/html') // => 'text/html'
req.is('text/*') // => 'text/*'

// When Content-Type is application/json
req.is('json') // => 'json'
req.is('application/json') // => 'application/json'
req.is('application/*') // => 'application/*'

req.is('html')
// => false

如需更多信息,或者如果您有问题或疑虑,请参阅 type-is

req.range(size[, options])

Range 标头解析器。

size 参数是资源的最大大小。

options 参数是一个可以具有以下属性的对象。

属性 类型 描述
combine 布尔值 指定是否应合并重叠和相邻范围,默认为 false。 当 true 时,范围将被组合并返回,就好像它们在标题中以这种方式指定一样。

将返回一个范围数组或指示解析错误的负数。

  • -2 表示格式错误的标头字符串
  • -1 表示无法满足的范围
// parse header from request
const range = req.range(1000)

// the type of the range
if (range.type === 'bytes') {
  // the ranges
  range.forEach((r) => {
    // do something with r.start and r.end
  })
}

响应

res 对象表示 Express 应用程序在收到 HTTP 请求时发送的 HTTP 响应。

在本文档中,按照惯例,该对象始终称为 res(HTTP 请求为 req),但其实际名称由您正在使用的回调函数的参数确定。

例如:

app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`)
})

但你也可以拥有:

app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`)
})

res对象是Node自带响应对象的增强版,支持所有内置字段和方法

Properties

res.app

此属性包含对使用中间件的 Express 应用程序实例的引用。

res.app 与请求对象中的 req.app 属性相同。

res.headersSent

指示应用程序是否为响应发送 HTTP 标头的布尔属性。

app.get('/', (req, res) => {
  console.log(res.headersSent) // false
  res.send('OK')
  console.log(res.headersSent) // true
})

res.locals

使用此属性设置在使用 res.render 呈现的模板中可访问的变量。 res.locals 上设置的变量在单个请求-响应周期内可用,并且不会在请求之间共享。

为了保留局部变量以用于请求之间的模板渲染,请改用 app.locals

此属性对于向应用程序中呈现的模板公开请求级信息(例如请求路径名称、经过身份验证的用户、用户设置等)很有用。

app.use((req, res, next) => {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user
  res.locals.authenticated = !req.user.anonymous
  next()
})

res.req

此属性包含对与此响应对象相关的 request object 的引用。

Methods

res.append(field [, value])

Express v4.11.0+ 支持 res.append()

将指定的 value 附加到 HTTP 响应标头 field。 如果尚未设置标头,则会创建具有指定值的标头。 value 参数可以是字符串或数组。

注意: 在 res.append() 之后调用 res.set() 将重置先前设置的标头值。

res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>'])
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly')
res.append('Warning', '199 Miscellaneous warning')

res.attachment([filename])

将 HTTP 响应 Content-Disposition 标头字段设置为 “attachment”。 如果给出了 filename,那么它会根据扩展名通过 res.type() 设置 Content-Type,并设置 Content-Disposition “filename=” 参数。

res.attachment()
// Content-Disposition: attachment

res.attachment('path/to/logo.png')
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png

res.cookie(name, value [, options])

将 cookie name 设置为 valuevalue 参数可以是字符串或转换为 JSON 的对象。

options 参数是一个可以具有以下属性的对象。

属性 类型 描述
domain 字符串 cookie 的域名。 默认为应用的域名。
encode 函数 用于 cookie 值编码的同步函数。 默认为 encodeURIComponent
expires 日期 格林威治标准时间 cookie 的到期日期。 如果未指定或设置为 0,则创建会话 cookie。
httpOnly 布尔值 将 cookie 标记为只能由 Web 服务器访问。
maxAge 数字 方便的选项,用于设置相对于当前时间的到期时间(以毫秒为单位)。
path 字符串 cookie 的路径。 默认为 “/”。
secure 布尔值 将 cookie 标记为仅与 HTTPS 一起使用。
signed 布尔值 指示是否应该对 cookie 进行签名。
sameSite 布尔值或字符串 “SameSite” Set-Cookie 属性的值。 更多信息请参见 https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-4.1.1

res.cookie() 所做的只是使用提供的选项设置 HTTP Set-Cookie 标头。 任何未指定的选项默认为 RFC 6265 中规定的值。

例如:

res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true })
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true })

encode 选项允许您选择用于 cookie 值编码的函数。 不支持异步函数。

示例用例: 您需要为组织中的另一个站点设置域范围的 cookie。 此其他站点(不受您的管理控制)不使用 URI 编码的 cookie 值。

// Default encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com' })
// Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'

// Custom encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com', encode: String })
// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'

maxAge 选项是一个方便的选项,用于设置 “expires” 相对于当前时间(以毫秒为单位)。 以下等效于上面的第二个示例。

res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })

你可以传递一个对象作为 value 参数; 然后它被序列化为 JSON 并由 bodyParser() 中间件解析。

res.cookie('cart', { items: [1, 2, 3] })
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 })

使用 cookie-parser 中间件时,此方法还支持签名 cookie。 只需将 signed 选项设置为 true。 然后 res.cookie() 将使用传递给 cookieParser(secret) 的秘密对值进行签名。

res.cookie('name', 'tobi', { signed: true })

稍后您可以通过 req.signedCookies 对象访问此值。

res.clearCookie(name [, options])

清除 name 指定的 cookie。 关于 options 对象的详细信息,请参见 res.cookie()

Web 浏览器和其他兼容的客户端只会在给定的 options 与给定给 res.cookie() 的相同(不包括 expiresmaxAge)时清除 cookie。

res.cookie('name', 'tobi', { path: '/admin' })
res.clearCookie('name', { path: '/admin' })

res.download(path [, filename] [, options] [, fn])

Express v4.16.0 及更高版本支持可选的 options 参数。

path 处的文件作为 “attachment” 传输。 通常,浏览器会提示用户下载。 默认情况下,Content-Disposition 标头 “filename=” 参数派生自 path 参数,但可以用 filename 参数覆盖。 如果 path 是相对的,那么它将基于进程的当前工作目录。

下表提供了有关 options 参数的详细信息。

Express v4.16.0 及更高版本支持可选的 options 参数。

属性 描述 默认 可用性
maxAge 设置 Cache-Control 标头的 max-age 属性(以毫秒为单位)或 ms 格式 中的字符串 0 4.16+
lastModified Last-Modified 标头设置为操作系统上文件的最后修改日期。 设置 false 以禁用它。 启用 4.16+
headers 包含与文件一起服务的 HTTP 标头的对象。 标题 Content-Disposition 将被 filename 参数覆盖。   4.16+
dotfiles 提供点文件的选项。 可能的值为 “allow”、”deny”、”ignore”。 “ignore” 4.16+
acceptRanges 启用或禁用接受范围请求。 true 4.16+
cacheControl 启用或禁用设置 Cache-Control 响应标头。 true 4.16+
immutable Cache-Control 响应标头中启用或禁用 immutable 指令。 如果启用,还应指定 maxAge 选项以启用缓存。 immutable 指令将阻止受支持的客户端在 maxAge 选项的生命周期内发出条件请求以检查文件是否已更改。 false 4.16+

该方法在传输完成或发生错误时调用回调函数 fn(err)。 如果指定了回调函数并且发生错误,则回调函数必须通过结束请求-响应循环或将控制权传递给下一个路由来显式处理响应过程。

res.download('/report-12345.pdf')

res.download('/report-12345.pdf', 'report.pdf')

res.download('/report-12345.pdf', 'report.pdf', (err) => {
  if (err) {
    // Handle error, but keep in mind the response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
})

res.end([data] [, encoding])

结束响应过程。 这个方法实际上来自 Node 核心,特别是 http.ServerResponse 的 response.end() 方法

用于在没有任何数据的情况下快速结束响应。 如果您需要用数据响应,请改用 res.send()res.json() 等方法。

res.end()
res.status(404).end()

res.format(object)

对请求对象的 Accept HTTP 标头(如果存在)执行内容协商。 它使用 req.accepts() 根据质量值排序的可接受类型为请求选择处理程序。 如果未指定标头,则调用第一个回调。 当没有找到匹配时,服务器响应 406 “不被接受”,或者调用 default 回调。

选择回调时设置 Content-Type 响应标头。 但是,您可以使用 res.set()res.type() 等方法在回调中更改它。

Accept 头字段设置为 “application/json” 或 “*/json” 时,以下示例将响应 { "message": "hey" }(但是如果它是 “*/*“,则响应将为 “hey”)。

res.format({
  'text/plain' () {
    res.send('hey')
  },

  'text/html' () {
    res.send('<p>hey</p>')
  },

  'application/json' () {
    res.send({ message: 'hey' })
  },

  default () {
    // log the request and respond with 406
    res.status(406).send('Not Acceptable')
  }
})

除了规范化的 MIME 类型之外,您还可以使用映射到这些类型的扩展名来实现稍微不那么冗长的实现:

res.format({
  text () {
    res.send('hey')
  },

  html () {
    res.send('<p>hey</p>')
  },

  json () {
    res.send({ message: 'hey' })
  }
})

res.get(field)

返回 field 指定的 HTTP 响应标头。 匹配不区分大小写。

res.get('Content-Type')
// => "text/plain"

res.json([body])

发送 JSON 响应。 此方法发送一个响应(具有正确的内容类型),该响应是使用 JSON.stringify() 转换为 JSON 字符串的参数。

参数可以是任何 JSON 类型,包括对象、数组、字符串、布尔值、数字或 null,您也可以使用它来将其他值转换为 JSON。

res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })

res.jsonp([body])

发送带有 JSONP 支持的 JSON 响应。 此方法与 res.json() 相同,只是它选择加入 JSONP 回调支持。

res.jsonp(null)
// => callback(null)

res.jsonp({ user: 'tobi' })
// => callback({ "user": "tobi" })

res.status(500).jsonp({ error: 'message' })
// => callback({ "error": "message" })

默认情况下,JSONP 回调名称只是 callback。 用 jsonp callback name 设置覆盖它。

以下是使用相同代码的 JSONP 响应的一些示例:

// ?callback=foo
res.jsonp({ user: 'tobi' })
// => foo({ "user": "tobi" })

app.set('jsonp callback name', 'cb')

// ?cb=foo
res.status(500).jsonp({ error: 'message' })
// => foo({ "error": "message" })

加入作为参数属性提供的 links 以填充响应的 Link HTTP 标头字段。

例如,以下调用:

res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5'
})

产生以下结果:

Link: <http://api.example.com/users?page=2>; rel="next",
      <http://api.example.com/users?page=5>; rel="last"

res.location(path)

将响应 Location HTTP 标头设置为指定的 path 参数。

res.location('/foo/bar')
res.location('http://example.com')
res.location('back')

“back” 的 path 值具有特殊含义,它指的是请求的 Referer 标头中指定的 URL。 如果未指定 Referer 标头,则它引用 “/”。

在对 URL 进行编码后,如果尚未编码,Express 会将指定的 URL 在 Location 标头中传递给浏览器,而不进行任何验证。

浏览器负责从当前 URL 或引用 URL 以及 Location 标头中指定的 URL 派生出预期的 URL; 并相应地重定向用户。

res.redirect([status,] path)

重定向到从指定 path 派生的 URL,指定 status,一个对应于 HTTP 状态码 的正整数。 如果未指定,则 status 默认为 “302 “Found”。

res.redirect('/foo/bar')
res.redirect('http://example.com')
res.redirect(301, 'http://example.com')
res.redirect('../login')

重定向可以是用于重定向到不同站点的完全限定 URL:

res.redirect('http://google.com')

重定向可以相对于主机名的根目录。 例如,如果应用程序位于 http://example.com/admin/post/new 上,则以下内容将重定向到 URL http://example.com/admin

res.redirect('/admin')

重定向可以相对于当前 URL。 例如,从 http://example.com/blog/admin/(注意尾部斜杠)开始,以下内容将重定向到 URL http://example.com/blog/admin/post/new

res.redirect('post/new')

http://example.com/blog/admin 重定向到 post/new(没有尾部斜杠),将重定向到 http://example.com/blog/post/new

如果您发现上述行为令人困惑,请将路径段视为目录(带有尾部斜杠)和文件,这将开始有意义。

路径相关的重定向也是可能的。 如果您在 http://example.com/admin/post/new,以下将重定向到 http://example.com/admin/post

res.redirect('..')

back 重定向将请求重定向回 referer,当引用者丢失时默认为 /

res.redirect('back')

res.render(view [, locals] [, callback])

呈现 view 并将呈现的 HTML 字符串发送到客户端。 可选参数:

  • locals,一个对象,其属性定义视图的局部变量。
  • callback,回调函数。 如果提供,该方法将返回可能的错误和呈现的字符串,但不执行自动响应。 当发生错误时,该方法在内部调用 next(err)

view 参数是一个字符串,它是要渲染的视图文件的文件路径。 这可以是绝对路径,也可以是相对于 views 设置的路径。 如果路径不包含文件扩展名,则 view engine 设置确定文件扩展名。 如果路径确实包含文件扩展名,那么 Express 将加载指定模板引擎的模块(通过 require())并使用加载模块的 __express 函数渲染它。

有关详细信息,请参阅 使用 Express 模板引擎

注意: view 参数执行文件系统操作,例如从磁盘读取文件和评估 Node.js 模块,因此出于安全原因不应包含来自最终用户的输入。

局部变量 cache 启用视图缓存。 设置为true,开发时缓存视图; 默认情况下在生产中启用视图缓存。

// send the rendered view to the client
res.render('index')

// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', (err, html) => {
  res.send(html)
})

// pass a local variable to the view
res.render('user', { name: 'Tobi' }, (err, html) => {
  // ...
})

res.send([body])

发送 HTTP 响应。

body 参数可以是 Buffer 对象、String、对象、BooleanArray。 例如:

res.send(Buffer.from('whoop'))
res.send({ some: 'json' })
res.send('<p>some html</p>')
res.status(404).send('Sorry, we cannot find that!')
res.status(500).send({ error: 'something blew up' })

此方法对简单的非流式响应执行许多有用的任务: 例如,它自动分配 Content-Length HTTP 响应头字段(除非之前定义)并提供自动 HEAD 和 HTTP 缓存新鲜度支持。

当参数为 Buffer 对象时,该方法将 Content-Type 响应头字段设置为 “application/octet-stream”,除非之前定义如下所示:

res.set('Content-Type', 'text/html')
res.send(Buffer.from('<p>some html</p>'))

当参数为 String 时,该方法将 Content-Type 设置为 “text/html”:

res.send('<p>some html</p>')

当参数为 ArrayObject 时,Express 以 JSON 表示形式响应:

res.send({ user: 'tobi' })
res.send([1, 2, 3])

res.sendFile(path [, options] [, fn])

Express v4.8.0 及更高版本支持 res.sendFile()

在给定的 path 传输文件。 根据文件名的扩展名设置 Content-Type 响应 HTTP 标头字段。 除非在选项对象中设置了 root 选项,否则 path 必须是文件的绝对路径。

此 API 提供对正在运行的文件系统上的数据的访问。 确保 (a) 将 path 参数构造为绝对路径的方式在包含用户输入时是安全的,或者 (b) 将 root 选项设置为目录的绝对路径以包含其中的访问。

当提供 root 选项时,允许 path 参数为相对路径,包括包含 ..。 Express 将验证作为 path 提供的相对路径将在给定的 root 选项中解析。

下表提供了有关 options 参数的详细信息。

属性 描述 默认 可用性
maxAge 设置 Cache-Control 标头的 max-age 属性(以毫秒为单位)或 ms 格式 中的字符串 0  
root 相对文件名的根目录。    
lastModified Last-Modified 标头设置为操作系统上文件的最后修改日期。 设置 false 以禁用它。 启用 4.9.0+
headers 包含与文件一起服务的 HTTP 标头的对象。    
dotfiles 提供点文件的选项。 可能的值为 “allow”、”deny”、”ignore”。 “ignore”  
acceptRanges 启用或禁用接受范围请求。 true 4.14+
cacheControl 启用或禁用设置 Cache-Control 响应标头。 true 4.14+
immutable Cache-Control 响应标头中启用或禁用 immutable 指令。 如果启用,还应指定 maxAge 选项以启用缓存。 immutable 指令将阻止受支持的客户端在 maxAge 选项的生命周期内发出条件请求以检查文件是否已更改。 false 4.16+

该方法在传输完成或发生错误时调用回调函数 fn(err)。 如果指定了回调函数并且发生错误,则回调函数必须通过结束请求-响应循环或将控制权传递给下一个路由来显式处理响应过程。

这是一个使用 res.sendFile 及其所有参数的示例。

app.get('/file/:name', (req, res, next) => {
  const options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true
    }
  }

  const fileName = req.params.name
  res.sendFile(fileName, options, (err) => {
    if (err) {
      next(err)
    } else {
      console.log('Sent:', fileName)
    }
  })
})

以下示例说明了使用 res.sendFile 为服务文件提供细粒度支持:

app.get('/user/:uid/photos/:file', (req, res) => {
  const uid = req.params.uid
  const file = req.params.file

  req.user.mayViewFilesFrom(uid, (yes) => {
    if (yes) {
      res.sendFile(`/uploads/${uid}/${file}`)
    } else {
      res.status(403).send("Sorry! You can't see that.")
    }
  })
})

如需更多信息,或者如果您有问题或疑虑,请参阅 send

res.sendStatus(statusCode)

将响应 HTTP 状态代码设置为 statusCode,并将注册的状态消息作为文本响应正文发送。 如果指定了未知状态代码,则响应正文将只是代码编号。

res.sendStatus(404)

res.statusCode 设置为无效的 HTTP 状态代码(超出范围 100599)时,某些版本的 Node.js 会抛出异常。 请查阅 HTTP 服务器文档以了解所使用的 Node.js 版本。

更多关于 HTTP 状态码

res.set(field [, value])

将响应的 HTTP 标头 field 设置为 value。 要一次设置多个字段,请将对象作为参数传递。

res.set('Content-Type', 'text/plain')

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345'
})

别名为 res.header(field [, value])

res.status(code)

设置响应的 HTTP 状态。 它是 Node 的 response.statusCode 的可链接别名。

res.status(403).end()
res.status(400).send('Bad Request')
res.status(404).sendFile('/absolute/path/to/404.png')

res.type(type)

Content-Type HTTP 标头设置为由指定 type 确定的 MIME 类型。 如果 type 包含 “/” 字符,则它将 Content-Type 设置为 type 的确切值,否则假定它是文件扩展名并使用 express.static.mime.lookup() 方法在映射中查找 MIME 类型。

res.type('.html') // => 'text/html'
res.type('html') // => 'text/html'
res.type('json') // => 'application/json'
res.type('application/json') // => 'application/json'
res.type('png') // => image/png:

res.vary(field)

将该字段添加到 Vary 响应标头(如果尚不存在)。

res.vary('User-Agent').render('docs')

路由

router 对象是中间件和路由的隔离实例。 你可以把它想象成一个只能执行中间件和路由功能的 “mini-application,”。 每个 Express 应用程序都有一个内置的应用程序路由。

路由的行为类似于中间件本身,因此您可以将其用作 app.use() 的参数或用作另一个路由的 use() 方法的参数。

顶级 express 对象具有创建新 router 对象的 Router() 方法。

一旦你创建了一个路由对象,你就可以像应用程序一样向它添加中间件和 HTTP 方法路由(例如 getputpost 等)。 例如:

// invoked for any requests passed to this router
router.use((req, res, next) => {
  // .. some logic here .. like any other middleware
  next()
})

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', (req, res, next) => {
  // ..
})

然后,您可以将路由用于特定的根 URL,以这种方式将您的路由分成文件甚至迷你应用程序。

// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router)

Methods

router.all(path, [callback, ...] callback)

此方法与 router.METHOD() 方法一样,只是它匹配所有 HTTP 方法(动词)。

此方法对于为特定路径前缀或任意匹配映射 “global” 逻辑非常有用。 例如,如果您将以下路由放在所有其他路由定义的顶部,则要求从该点开始的所有路由都需要身份验证,并自动加载用户。 请记住,这些回调不必充当端点; loadUser可以执行一个任务,然后调用next()继续匹配后续路由。

router.all('*', requireAuthentication, loadUser)

或等价物:

router.all('*', requireAuthentication)
router.all('*', loadUser)

另一个例子是列入白名单的 “global” 功能。 这里的例子很像以前,但它只限制以 “/api” 为前缀的路径:

router.all('/api/*', requireAuthentication)

router.METHOD(path, [callback, ...] callback)

router.METHOD() 方法在 Express 中提供路由功能,其中 METHOD 是 HTTP 方法之一,例如 GET、PUT、POST 等,小写。 因此,实际的方法是 router.get()router.post()router.put() 等等。

如果 router.get() 之前的路径没有调用 router.head(),则除了 GET 方法之外,还会为 HTTP HEAD 方法自动调用 router.get() 函数。

您可以提供多个回调,并且所有回调都被平等对待,并且表现得像中间件,除了这些回调可能会调用 next('route') 以绕过剩余的路由回调。 您可以使用此机制对路由执行前置条件,然后在没有理由继续匹配路由时将控制权传递给后续路由。

以下片段说明了可能的最简单的路由定义。 Express 将路径字符串转换为正则表达式,在内部用于匹配传入的请求。 执行这些匹配时不考虑查询字符串,例如 “GET /” 将匹配以下路由,”GET /?name=tobi” 也是如此。

router.get('/', (req, res) => {
  res.send('hello world')
})

您还可以使用正则表达式——如果您有非常具体的约束,则很有用,例如以下将匹配 “GET /commits/71dbb9c” 和 “GET /commits/71dbb9c..4c084f9”。

router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, (req, res) => {
  const from = req.params[0]
  const to = req.params[1] || 'HEAD'
  res.send(`commit range ${from}..${to}`)
})

您可以使用 next 原语根据特定的程序状态在不同的中间件函数之间实现流控制。 使用字符串 'router' 调用 next 将导致该路由上所有剩余的路由回调被绕过。

以下示例说明了 next('router') 的用法。

function fn (req, res, next) {
  console.log('I come here')
  next('router')
}
router.get('/foo', fn, (req, res, next) => {
  console.log('I dont come here')
})
router.get('/foo', (req, res, next) => {
  console.log('I dont come here')
})
app.get('/foo', (req, res) => {
  console.log(' I come here too')
  res.end('good')
})

router.param(name, callback)

为路由参数添加回调触发器,其中name为参数名称,callback为回调函数。 尽管 name 在技术上是可选的,但从 Express v4.11.0 开始不推荐使用此方法(见下文)。

回调函数的参数为​​:

  • req,请求对象。
  • res,响应对象。
  • next,表示下一个中间件函数。
  • name 参数的值。
  • 参数的名称。

app.param() 不同,router.param() 不接受路由参数数组。

例如,当 :user 出现在路由路径中时,您可以映射用户加载逻辑以自动将 req.user 提供给路由,或对参数输入执行验证。

router.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err)
    } else if (user) {
      req.user = user
      next()
    } else {
      next(new Error('failed to load user'))
    }
  })
})

参数回调函数在定义它们的路由上是本地的。 它们不会被安装的应用程序或路由继承。 因此,在 router 上定义的参数回调将仅由在 router 路由上定义的路由参数触发。

一个参数回调在请求-响应周期中只会被调用一次,即使该参数在多个路由中匹配,如下例所示。

router.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE')
  next()
})

router.get('/user/:id', (req, res, next) => {
  console.log('although this matches')
  next()
})

router.get('/user/:id', (req, res) => {
  console.log('and this matches too')
  res.end()
})

GET /user/42 上,打印以下内容:

CALLED ONLY ONCE
although this matches
and this matches too

以下部分描述了 router.param(callback),自 v4.11.0 起已弃用。

router.param(name, callback) 方法的行为可以通过只向 router.param() 传递一个函数来完全改变。 这个函数是 router.param(name, callback) 应该如何表现的自定义实现——它接受两个参数并且必须返回一个中间件。

此函数的第一个参数是应捕获的 URL 参数的名称,第二个参数可以是任何可能用于返回中间件实现的 JavaScript 对象。

函数返回的中间件决定了捕获 URL 参数时发生的行为。

在此示例中,将 router.param(name, callback) 签名修改为 router.param(name, accessId)router.param() 现在将接受名称和号码,而不是接受名称和回调。

const express = require('express')
const app = express()
const router = express.Router()

// customizing the behavior of router.param()
router.param((param, option) => {
  return (req, res, next, val) => {
    if (val === option) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

// using the customized router.param()
router.param('id', 1337)

// route to trigger the capture
router.get('/user/:id', (req, res) => {
  res.send('OK')
})

app.use(router)

app.listen(3000, () => {
  console.log('Ready')
})

在此示例中,router.param(name, callback) 签名保持不变,但没有使用中间件回调,而是定义了自定义数据类型检查函数来验证用户 ID 的数据类型。

router.param((param, validator) => {
  return (req, res, next, val) => {
    if (validator(val)) {
      next()
    } else {
      res.sendStatus(403)
    }
  }
})

router.param('id', (candidate) => {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate)
})

router.route(path)

返回单个路由的实例,然后您可以使用该实例处理带有可选中间件的 HTTP 动词。 使用 router.route() 来避免重复的路由命名,从而避免输入错误。

在上面的 router.param() 示例的基础上,以下代码显示了如何使用 router.route() 来指定各种 HTTP 方法处理程序。

const router = express.Router()

router.param('user_id', (req, res, next, id) => {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id,
    name: 'TJ'
  }
  next()
})

router.route('/users/:user_id')
  .all((req, res, next) => {
  // runs for all HTTP verbs first
  // think of it as route specific middleware!
    next()
  })
  .get((req, res, next) => {
    res.json(req.user)
  })
  .put((req, res, next) => {
  // just an example of maybe updating the user
    req.user.name = req.params.name
    // save user ... etc
    res.json(req.user)
  })
  .post((req, res, next) => {
    next(new Error('not implemented'))
  })
  .delete((req, res, next) => {
    next(new Error('not implemented'))
  })

此方法重用单个 /users/:user_id 路径并为各种 HTTP 方法添加处理程序。

注意: 当您使用 router.route() 时,中间件排序基于路由创建的时间,而不是方法处理程序添加到路由的时间。 为此,您可以认为方法处理程序属于添加它们的路由。

router.use([path], [function, ...] function)

使用指定的中间件函数或函数,带有可选的挂载路径 path,默认为 “/”。

此方法与 app.use() 类似。 下面描述了一个简单的示例和用例。 有关详细信息,请参阅 app.use()

中间件就像一个水管: 请求从定义的第一个中间件函数开始,并按照 “down” 中间件堆栈处理它们匹配的每个路径的方式工作。

const express = require('express')
const app = express()
const router = express.Router()

// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use((req, res, next) => {
  console.log('%s %s %s', req.method, req.url, req.path)
  next()
})

// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', (req, res, next) => {
  // ... maybe some additional /bar logging ...
  next()
})

// always invoked
router.use((req, res, next) => {
  res.send('Hello World')
})

app.use('/foo', router)

app.listen(3000)

“mount” 路径被剥离并且对中间件函数不可见。 此功能的主要效果是挂载的中间件函数可以在不更改代码的情况下运行,无论其 “prefix” 路径名如何。

使用 router.use() 定义中间件的顺序非常重要。 它们按顺序调用,因此顺序定义了中间件优先级。 例如,通常记录器是您将使用的第一个中间件,以便记录每个请求。

const logger = require('morgan')

router.use(logger())
router.use(express.static(path.join(__dirname, 'public')))
router.use((req, res) => {
  res.send('Hello')
})

现在假设您想忽略对静态文件的日志记录请求,但继续记录 logger() 之后定义的路由和中间件。 在添加记录器中间件之前,您只需将对 express.static() 的调用移至顶部:

router.use(express.static(path.join(__dirname, 'public')))
router.use(logger())
router.use((req, res) => {
  res.send('Hello')
})

另一个例子是从多个目录提供文件,让 “./public” 优先于其他:

app.use(express.static(path.join(__dirname, 'public')))
app.use(express.static(path.join(__dirname, 'files')))
app.use(express.static(path.join(__dirname, 'uploads')))

router.use() 方法还支持命名参数,因此您的其他路由的挂载点可以从使用命名参数的预加载中受益。

注意: 尽管这些中间件函数是通过特定的路由添加的,但它们运行时是由它们所连接的路径(而不是路由)定义的。 因此,如果路由匹配,通过一个路由添加的中间件可以为其他路由运行。 例如,此代码显示了安装在同一路径上的两个不同路由:

const authRouter = express.Router()
const openRouter = express.Router()

authRouter.use(require('./authenticate').basic(usersdb))

authRouter.get('/:user_id/edit', (req, res, next) => {
  // ... Edit user UI ...
})
openRouter.get('/', (req, res, next) => {
  // ... List users ...
})
openRouter.get('/:user_id', (req, res, next) => {
  // ... View user ...
})

app.use('/users', authRouter)
app.use('/users', openRouter)

即使身份验证中间件是通过 authRouter 添加的,它也会在 openRouter 定义的路由上运行,因为两个路由都安装在 /users 上。 为避免此行为,请为每个路由使用不同的路径。