路由

_路由_表示应用程序端点 (URI) 的定义以及端点响应客户机请求的方式。 有关路由的简介,请参阅基本路由。 For an introduction to routing, see Basic routing.

我们所使用的 app 与 HTTP 方法相对应的 Express 对象方法来定义路由,如 app.get() 用于处理 GET 请求,而 app.post 则用于处理 POST 请求。 For a full list, see app.METHOD. You can also use app.all() to handle all HTTP methods and app.use() to specify middleware as the callback function (See Using middleware for details).

这些路由方法都指定了回调函数(或者:“处理程序函数”),当程序接收到指定的路由(端点)的时候(也就是说 HTTP 方法请求时被调用),来调用回调函数,换句话说就是应用程序监听与指定路由和方法匹配的请求,当检测到匹配时,他会调用对应的回调函数。 In other words, the application “listens” for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.

In fact, the routing methods can have more than one callback function as arguments. With multiple callback functions, it is important to provide next as an argument to the callback function and then call next() within the body of the function to hand off control to the next callback.

以下代码是非常基本的路由示例。

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

// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
  res.send('hello world')
})

路由方法

路由方法派生自 HTTP 方法之一,附加到 express 类的实例。

以下代码是为访问应用程序根目录的 GET 和 POST 方法定义的路由示例。

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

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

Express supports methods that correspond to all HTTP request methods: get, post, and so on. For a full list, see app.METHOD.

有一种特殊路由方法:app.all(),它并非派生自 HTTP 方法。该方法用于在所有请求方法的路径中装入中间件函数。 在以下示例中,无论您使用 GET、POST、PUT、DELETE 还是在 http 模块中支持的其他任何 HTTP 请求方法,都将为针对“/secret”的请求执行处理程序。

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

路由路径

路由路径与请求方法相结合,用于定义可以在其中提出请求的端点。路由路径可以是字符串、字符串模式或正则表达式。 Route paths can be strings, string patterns, or regular expressions.

Caution

In express 5, the characters ?, +, *, [], and () are handled differently than in version 4, please review the migration guide for more information.

Caution

In express 4, regular expression characters such as $ need to be escaped with a \.

Note

Express uses path-to-regexp for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. Express Playground Router is a handy tool for testing basic Express routes, although it does not support pattern matching.

Warning

Query strings are not part of the route path.

以下是基于字符串的路由路径的一些示例。

此路由路径将请求与 /random.text 匹配。

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

此路由路径将请求与 /about 匹配。

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

此路由路径将请求与根路由 / 匹配。

app.get('/random.text', (req, res) => {
  res.send('random.text')
})

以下是基于字符串模式的路由路径的一些示例。

Caution

The string patterns in Express 5 no longer work. Please refer to the migration guide for more information.

此路由路径将匹配 /abe/abcde

app.get('/ab?cd', (req, res) => {
  res.send('ab?cd')
})

此路由路径将匹配 abcdabbcdabbbcd 等。

app.get('/ab+cd', (req, res) => {
  res.send('ab+cd')
})

此路由路径将匹配 abcdabxcdabRABDOMcdab123cd 等。

app.get('/ab*cd', (req, res) => {
  res.send('ab*cd')
})

此路由路径将匹配 acdabcd

app.get('/ab(cd)?e', (req, res) => {
  res.send('ab(cd)?e')
})

基于正则表达式的路由路径的示例:

此路由路径将匹配名称中具有“a”的所有路由。

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

此路由路径将匹配 butterflydragonfly,但是不匹配 butterflymandragonfly man 等。

app.get(/.*fly$/, (req, res) => {
  res.send('/.*fly$/')
})

路由处理程序

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.

Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }

To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.

app.get('/users/:userId/books/:bookId', (req, res) => {
  res.send(req.params)
})

The name of route parameters must be made up of “word characters” ([A-Za-z0-9_]).

Since the hyphen (-) and the dot (.) are interpreted literally, they can be used along with route parameters for useful purposes.

Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }

Caution

In express 5, Regexp characters are not supported in route paths, for more information please refer to the migration guide.

To have more control over the exact string that can be matched by a route parameter, you can append a regular expression in parentheses (()):

Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}

Warning

Because the regular expression is usually part of a literal string, be sure to escape any \ characters with an additional backslash, for example \\d+.

Warning

In Express 4.x, the * character in regular expressions is not interpreted in the usual way. As a workaround, use {0,} instead of *. This will likely be fixed in Express 5.

Route handlers

您可以提供多个回调函数,以类似于中间件的行为方式来处理请求。唯一例外是这些回调函数可能调用 next('route') 来绕过剩余的路由回调。您可以使用此机制对路由施加先决条件,在没有理由继续执行当前路由的情况下,可将控制权传递给后续路由。 The only exception is that these callbacks might invoke next('route') to bypass the remaining route callbacks. You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there’s no reason to proceed with the current route.

Route handlers can be in the form of a function, an array of functions, or combinations of both, as shown in the following examples.

单个回调函数可以处理一个路由。例如: For example:

app.get('/example/a', (req, res) => {
  res.send('Hello from A!')
})

多个回调函数可以处理一个路由(确保您指定 next 对象)。例如: For example:

app.get('/example/b', (req, res, next) => {
  console.log('the response will be sent by the next function ...')
  next()
}, (req, res) => {
  res.send('Hello from B!')
})

一组回调函数可以处理一个路由。例如: For example:

const cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

const cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

const cb2 = function (req, res) {
  res.send('Hello from C!')
}

app.get('/example/c', [cb0, cb1, cb2])

独立函数与一组函数的组合可以处理一个路由。例如: For example:

const cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}

const cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}

app.get('/example/d', [cb0, cb1], (req, res, next) => {
  console.log('the response will be sent by the next function ...')
  next()
}, (req, res) => {
  res.send('Hello from D!')
})

响应方法

下表中响应对象 (res) 的方法可以向客户机发送响应,并终止请求/响应循环。如果没有从路由处理程序调用其中任何方法,客户机请求将保持挂起状态。 If none of these methods are called from a route handler, the client request will be left hanging.

方法 描述
res.download() 提示将要下载文件。
res.end() 结束响应进程。
res.json() 发送 JSON 响应。
res.jsonp() 在 JSONP 的支持下发送 JSON 响应。
res.redirect() 重定向请求。
res.render() 呈现视图模板。
res.send() 发送各种类型的响应。
res.sendFile() 以八位元流形式发送文件。
res.sendStatus() 设置响应状态码并以响应主体形式发送其字符串表示。

app.route()

您可以使用 app.route() 为路由路径创建可链接的路由处理程序。 因为在单一位置指定路径,所以可以减少冗余和输入错误。有关路由的更多信息,请参阅 Router() 文档。 Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos. For more information about routes, see: Router() documentation.

以下是使用 app.route() 定义的链式路由处理程序的示例。

app.route('/book')
  .get((req, res) => {
    res.send('Get a random book')
  })
  .post((req, res) => {
    res.send('Add a book')
  })
  .put((req, res) => {
    res.send('Update the book')
  })

express.Router

使用 express.Router 类来创建可安装的模块化路由处理程序。Router 实例是完整的中间件和路由系统;因此,常常将其称为“微型应用程序”。 A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.

以下示例将路由器创建为模块,在其中装入中间件,定义一些路由,然后安装在主应用程序的路径中。

在应用程序目录中创建名为 birds.js 的路由器文件,其中包含以下内容:

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

// middleware that is specific to this router
const timeLog = (req, res, next) => {
  console.log('Time: ', Date.now())
  next()
}
router.use(timeLog)

// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page')
})
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds')
})

module.exports = router

接着,在应用程序中装入路由器模块:

const birds = require('./birds')

// ...

app.use('/birds', birds)

此应用程序现在可处理针对 /birds/birds/about 的请求,调用特定于此路由的 timeLog 中间件函数。

But if the parent route /birds has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the mergeParams option to the Router constructor reference.

const router = express.Router({ mergeParams: true })
Edit this page