Routing路由

Routing refers to how an application’s endpoints (URIs) respond to client requests.路由是指应用程序的端点(URI)如何响应客户端请求。 For an introduction to routing, see Basic routing.有关布线的介绍,请参阅基本路线

You define routing using methods of the Express app object that correspond to HTTP methods; for example, app.get() to handle GET requests and app.post to handle POST requests. 您可以使用Expressapp对象的方法定义路由,这些方法对应于HTTP方法;例如,app.get()用于处理GET请求,app.post用于处理POST请求。For a full list, see app.METHOD. 有关完整列表,请参阅app.METHODYou 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).您还可以使用app.all()处理所有HTTP方法,并使用app.use()将中间件指定为回调函数(有关详细信息,请参阅使用中间件)。

These routing methods specify a callback function (sometimes called “handler functions”) called when the application receives a request to the specified route (endpoint) and HTTP method. 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.这些路由方法指定了一个回调函数(有时称为“处理函数”),当应用程序收到对指定路由(端点)和HTTP方法的请求时,会调用该函数。换句话说,应用程序“监听”与指定路由和方法匹配的请求,当它检测到匹配时,它会调用指定的回调函数。

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.对于多个回调函数,重要的是为回调函数提供next作为参数,然后在函数体内调用next()将控制权移交给下一个回调函数。

The following code is an example of a very basic route.以下代码是一个非常基本的路由示例。

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')
})

Route methods路由方法

A route method is derived from one of the HTTP methods, and is attached to an instance of the express class.路由方法从HTTP方法之一派生,并附加到express类的实例。

The following code is an example of routes that are defined for the GET and the POST methods to the root of the app.以下代码是为GETPOST方法定义的到应用程序根的路由示例。

// 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.Express支持与所有HTTP请求方法相对应的方法:getpost等。 For a full list, see app.METHOD.有关完整列表,请参阅app.METHOD

There is a special routing method, app.all(), used to load middleware functions at a path for all HTTP request methods. 有一种特殊的路由方法app.all(),用于在所有HTTP请求方法的路径上加载中间件函数。For example, the following handler is executed for requests to the route "/secret" whether using GET, POST, PUT, DELETE, or any other HTTP request method supported in the http module.例如,对路由"/secret"的请求执行以下处理程序,无论是使用GETPOSTPUTDELETE还是HTTP模块中支持的任何其他HTTP请求方法。

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

Route paths路由路径

Route paths, in combination with a request method, define the endpoints at which requests can be made. 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.在express 5中,字符?+*[]()的处理方式与版本4不同,请查看迁移指南以获取更多信息。

Caution小心

In express 4, regular expression characters such as $ need to be escaped with a \.在express 4中,$等正则表达式字符需要用\转义。

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使用path-to-regexp来匹配路由路径;有关定义路由路径的所有可能性,请参阅path-to-regexp文档。Express Playground Router is a handy tool for testing basic Express routes, although it does not support pattern matching.Express Playground Router是一个方便的工具,用于测试基本的Express路由,尽管它不支持模式匹配。

Warning警告

Query strings are not part of the route path.查询字符串不是路由路径的一部分。

Route paths based on strings基于字符串的路由路径

This route path will match requests to the root route, /.此路由路径将匹配对根路由/的请求。

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

This route path will match requests to /about.此路由路径将匹配对/about的请求。

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

This route path will match requests to /random.text.此路由路径将匹配对/random.text的请求。

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

Route paths based on string patterns基于字符串模式的路由路径

Caution小心

The string patterns in Express 5 no longer work. Please refer to the migration guide for more information.Express 5中的字符串模式不再有效。有关更多信息,请参阅迁移指南

This route path will match acd and abcd.此路由路径将匹配acdabcd

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

This route path will match abcd, abbcd, abbbcd, and so on.此路由路径将匹配abcdabbcdabbbcd等。

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

This route path will match abcd, abxcd, abRANDOMcd, ab123cd, and so on.此路由路径将匹配abcdabxcdabRANDOMcdab123cd等。

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

This route path will match /abe and /abcde.此路由路径将匹配/abe/abcde

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

Route paths based on regular expressions基于正则表达式的路由路径

This route path will match anything with an “a” in it.此路由路径将匹配任何包含“a”的路径。

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

This route path will match butterfly and dragonfly, but not butterflyman, dragonflyman, and so on.这条路线路径将匹配butterflydragonfly,但不匹配butterflymandragonflyman等。

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

Route parameters路线参数

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. 路由参数是命名的URL段,用于捕获在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.捕获的值填充在req.params对象中,路径中指定的路由参数的名称作为其各自的键。

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_]).路由参数的名称必须由“单词字符”([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.在express 5中,路由路径中不支持Regexp字符,有关更多信息,请参阅迁移指南

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+.因为正则表达式通常是文字字符串的一部分,所以一定要用额外的反斜杠转义任何\字符,例如\\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.在Express 4x中,正则表达式中的*字符不会以通常的方式解释。作为解决方法,请使用{0,}而不是*。这可能会在Express 5中得到修复。

Route handlers路由处理程序

You can provide multiple callback functions that behave like middleware to handle a request. 您可以提供多个回调函数,其行为类似于中间件来处理请求。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.唯一的例外是,这些回调可能会调用next('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.路由处理程序可以是函数、函数数组或两者的组合,如以下示例所示。

A single callback function can handle a route. For example:一个回调函数可以处理一个路由。例如:

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

More than one callback function can handle a route (make sure you specify the next object). For example:多个回调函数可以处理一个路由(请确保指定next对象)。例如:

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!')
})

An array of callback functions can handle a route. 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])

A combination of independent functions and arrays of functions can handle a route. 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!')
})

Response methods响应方式

The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.下表中响应对象(res)的方法可以向客户端发送响应,并终止请求-响应循环。如果路由处理程序没有调用这些方法,则客户端请求将挂起。

Method方法 Description描述
res.download() Prompt a file to be downloaded.提示下载文件。
res.end() End the response process.结束响应过程。
res.json() Send a JSON response.发送JSON响应。
res.jsonp() Send a JSON response with JSONP support.发送支持JSONP的JSON响应。
res.redirect() Redirect a request.重定向请求。
res.render() Render a view template.渲染视图样板。
res.send() Send a response of various types.发送各种类型的响应。
res.sendFile() Send a file as an octet stream.以八位字节流的形式发送文件。
res.sendStatus() Set the response status code and send its string representation as the response body.设置响应状态代码,并将其字符串表示形式作为响应正文发送。

app.route()

You can create chainable route handlers for a route path by using app.route().您可以使用app.route()为路由路径创建可链接的路由处理程序。 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.有关路由的更多信息,请参阅:Router()文档

Here is an example of chained route handlers that are defined by using app.route().这是一个使用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

Use the express.Router class to create modular, mountable route handlers. 使用express.Router类创建模块化、可装载的路由处理程序。A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.Router实例是一个完整的中间件和路由系统;因此,它通常被称为“mini-app”。

The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.以下示例将路由器创建为模块,在其中加载中间件函数,定义一些路由,并将路由器模块挂载到主应用程序中的路径上。

Create a router file named birds.js in the app directory, with the following content:在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

Then, load the router module in the app:然后,在应用程序中加载路由器模块:

const birds = require('./birds')

// ...

app.use('/birds', birds)

The app will now be able to handle requests to /birds and /birds/about, as well as call the timeLog middleware function that is specific to the route.该应用程序现在将能够处理对/birds/birds/about的请求,并调用特定于该路由的timeLog中间件函数。

But if the parent route /birds has path parameters, it will not be accessible by default from the sub-routes. 但是,如果父路线/birds有路径参数,则默认情况下无法从子路线访问它。To make it accessible, you will need to pass the mergeParams option to the Router constructor reference.为了使其可访问,您需要将mergeParams选项传递给Router构造函数引用

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