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;您可以使用对应于HTTP方法的Express app对象的方法定义路由;for example, app.get() to handle GET requests and app.post to handle POST requests.例如,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.这些路由方法指定一个回调函数(有时称为“处理函数”),当应用程序接收到对指定路由(端点)和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.对于多个回调函数,重要的是提供next作为回调函数的参数,然后在函数体中调用next(),将控制权移交给下一个回调函数。

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

var express = require('express')
var app = express()

// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (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.下面的代码是为GET和POST方法定义的到应用程序根目录的路由示例。

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

// POST method route
app.post('/', function (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”的请求执行以下处理程序,无论是使用GET、POST、PUT、DELETE还是http模块中支持的任何其他HTTP请求方法。

app.all('/secret', function (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.路由路径可以是字符串、字符串模式或正则表达式。

The characters ?, +, *, and () are subsets of their regular expression counterparts. 字符?+*()是其正则表达式对应项的子集。The hyphen (-) and the dot (.) are interpreted literally by string-based paths.连字符(-)和点(.)由基于字符串的路径逐字解释。

If you need to use the dollar character ($) in a path string, enclose it escaped within ([ and ]). 如果需要在路径字符串中使用美元字符($),请将其括在([])中。For example, the path string for requests at “/data/$book”, would be “/data/([\$])book”.例如,位于“/data/$book”的请求的路径字符串将是“/data/([\$])book”。

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

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

Here are some examples of route paths based on strings.下面是一些基于字符串的路由路径示例。

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

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

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

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

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

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

Here are some examples of route paths based on string patterns.下面是一些基于字符串模式的路由路径示例。

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

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

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

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

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

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

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

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

Examples of route paths based on regular expressions:基于正则表达式的路由路径示例:

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

app.get(/a/, function (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$/, function (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', function (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" }

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"}

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+

In Express 4.x, the * character in regular expressions is not interpreted in the usual way. 在Express4.x中,正则表达式中的*字符不是以通常的方式解释的As a workaround, use {0,} instead of *. 作为解决方法,请使用{0,}而不是*This will likely be fixed in Express 5.这可能会在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. 唯一的例外是,这些回调可能调用next('route')来绕过其余的路由回调。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.路由处理程序可以是函数、函数数组或两者的组合形式,如以下示例所示。

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

app.get('/example/a', function (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:例如:

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

An array of callback functions can handle a route. For example:回调函数数组可以处理路由。例如:

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

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

var 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:独立函数和函数数组的组合可以处理路由。例如:

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

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

app.get('/example/d', [cb0, cb1], function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (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. 下表中响应对象(res)上的方法可以向客户端发送响应,并终止请求-响应周期。If none of these methods are called from a route handler, the client request will be left hanging.如果这些方法都没有从路由处理程序调用,那么客户端请求将挂起。

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(function (req, res) {
    res.send('Get a random book')
  })
  .post(function (req, res) {
    res.send('Add a book')
  })
  .put(function (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实例是一个完整的中间件和路由系统;因此,它通常被称为“迷你应用程序”。

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:在应用程序目录中创建名为birds.js的路由器文件,包含以下内容:

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

// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
  console.log('Time: ', Date.now())
  next()
})
// define the home page route
router.get('/', function (req, res) {
  res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
  res.send('About birds')
})

module.exports = router

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

var 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中间件功能。