Roteamento
Routing refere-se a como os endpoints de um aplicativo (URIs) respondem às solicitações do cliente. Para uma introdução ao roteamento, veja Roteamento básico.
Você define roteamento usando métodos do objeto Express app que correspondem aos métodos HTTP;
por exemplo, app. et() para lidar com solicitações GET e app.post para lidar com solicitações 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).
Em outras palavras, o aplicativo “listas” para solicitações que correspondem com a(s) rota(s) e método(s) especificado(s), e quando ela detecta uma correspondência, ela chama a função de retorno de chamada especificado. Em outras palavras, o aplicativo “listas” para solicitações que correspondem com a(s) rota(s) e método(s) especificado(s), e quando ela detecta uma correspondência, ela chama a função de retorno de chamada especificado.
Na verdade, os métodos de roteamento podem ter mais de uma função de callback como argumentos.
Com múltiplas funções de callback, é importante fornecer next como um argumento para a função de callback e então chamar next() dentro do corpo da função para liberar o controle
para a próxima callback.
O código a seguir é um exemplo de uma rota muito básica.
const express = require('express');const app = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req, res) => { res.send('hello world');});import express from 'express';
const app = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req, res) => { res.send('hello world');});import express, { type Express, type Request, type Response } from 'express';
const app: Express = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req: Request, res: Response) => { res.send('hello world');});Métodos de rota
Um método de route é derivado de um dos métodos HTTP e é anexado a uma instância da classe ‘express’.
O código a seguir é um exemplo de rotas que são definidas para os métodos GET e POST para a raiz do aplicativo.
// GET method routeapp.get('/', (req, res) => { res.send('GET request to the homepage');});
// POST method routeapp.post('/', (req, res) => { res.send('POST request to the homepage');});import { type Request, type Response } from 'express';
// GET method routeapp.get('/', (req: Request, res: Response) => { res.send('GET request to the homepage');});
// POST method routeapp.post('/', (req: Request, res: Response) => { res.send('POST request to the homepage');});Expresso suporta métodos que correspondem a todos os métodos de requisição HTTP: get, post, e assim por diante.
For a full list, see app.METHOD.
Há um método de roteamento especial, app.all(), usado para carregar funções de middleware em um caminho para os métodos de requisição HTTP. For example, the following handler is executed for requests to the route "/secret" whether using GET, QUERY, POST, PUT, DELETE, or any other HTTP request method supported in the http module.
app.all('/secret', (req, res, next) => { console.log('Accessing the secret section ...'); next(); // pass control to the next handler});import { type Request, type Response, type NextFunction } from 'express';
app.all('/secret', (req: Request, res: Response, next: NextFunction) => { console.log('Accessing the secret section ...'); next(); // pass control to the next handler});Caminho da rota
Roteamento, em combinação com um método de solicitação, defina os pontos de extremidade em que as solicitações podem ser feitas. Caminhos de rota podem ser strings ou expressões regulares. They can also capture values from the URL, as described in Route parameters below.
Note
Expresso usa path-to-regexp v8 para combinar com os caminhos da rota; veja a documentação pai-para-regexp para todas as possibilidades de definir caminhos da rota. Express Playground Router é uma ferramenta útil para testar rotas Express, embora não suporte correspondência de padrões.
Caminhos do texto
Os caminhos de strings correspondem exatamente às requisições. O ponto (.) e o hífen (-) são interpretados literalmente.
Warning
app.get('/', (req, res) => { res.send('root');});
app.get('/about', (req, res) => { res.send('about');});
app.get('/random.text', (req, res) => { res.send('random.text');});import { type Request, type Response } from 'express';
app.get('/', (req: Request, res: Response) => { res.send('root');});
app.get('/about', (req: Request, res: Response) => { res.send('about');});
app.get('/random.text', (req: Request, res: Response) => { res.send('random.text');});Caution
The characters ?, +, *, [], (), and ! are reserved and cannot be used as literal characters in route paths, and braces are reserved for optional segments. Use \ para escapar deles se necessário.
Expressões regulares
Você também pode usar expressões regulares como caminhos de rota. Isto é útil quando você precisa de uma lógica de correspondência mais complexa.
// Matches any path containing "a"app.get(/a/, (req, res) => { res.send('/a/');});
// Matches paths ending with "fly" (butterfly, dragonfly, etc.)app.get(/.*fly$/, (req, res) => { res.send('/.*fly$/');});import { type Request, type Response } from 'express';
// Matches any path containing "a"app.get(/a/, (req: Request, res: Response) => { res.send('/a/');});
// Matches paths ending with "fly" (butterfly, dragonfly, etc.)app.get(/.*fly$/, (req: Request, res: Response) => { res.send('/.*fly$/');});Parâmetros de rota
Parâmetros de rota são denominados segmentos de URL que são usados para capturar os valores especificados em sua posição na URL. Os valores capturados são preenchidos no objeto req.params, com o nome do parâmetro de rota especificado no caminho como suas respectivas chaves. They come in three forms: named parameters (:name), wildcards (*name), and optional segments, which wrap either of them in braces.
Named parameters
Named parameters capture a single path segment at their position in the URL, or part of one when combined with literal characters, as shown further below.
Route path: /users/:userId/books/:bookIdRequest URL: http://localhost:3000/users/34/books/8989req.params: { "userId": "34", "bookId": "8989" }Para definir rotas com parâmetros de rota, simplesmente especifique os parâmetros de rota no caminho da rota, conforme mostrado abaixo.
app.get('/users/:userId/books/:bookId', (req, res) => { res.send(req.params);});In TypeScript, @types/express infers the parameters from the route path, so in the handler above
req.params.userId and req.params.bookId are already typed as string with no extra annotation.
Reading a name that is not in the route (such as req.params.other) is a type error. You only need
to annotate the parameters when the handler is defined separately from the route, because the type
checker can no longer see the path. In that case, pass them as the first type argument of Request:
import { type Request, type Response } from 'express';
const sendParams = (req: Request<{ userId: string; bookId: string }>, res: Response) => { res.send(req.params);};
app.get('/users/:userId/books/:bookId', sendParams);Caution
The name of route parameters must be a valid JavaScript identifier. Other names can be used by quoting them, for example :"user-name".
Como o hífen (-) e o ponto (.) são interpretados literalmente, eles podem ser usados juntamente com parâmetros de rota para fins úteis.
Route path: /flights/:from-:toRequest URL: http://localhost:3000/flights/LAX-SFOreq.params: { "from": "LAX", "to": "SFO" }Route path: /plantae/:genus.:speciesRequest URL: http://localhost:3000/plantae/Prunus.persicareq.params: { "genus": "Prunus", "species": "persica" }Caution
Regexp characters are not supported inside string paths, so a parameter cannot be restricted with a suffix such as :userId(\d+). Use an array of paths or a full regular expression instead.
Veja a sintaxe correspondente à trajetória para obter mais informações.
Wildcards
Caracteres curinga correspondem a qualquer caminho após um prefixo. Like other route parameters they must have a name, but they are captured as an array of path segments instead of a string.
app.get('/files/*filepath', (req, res) => { // GET /files/images/logo.png console.dir(req.params.filepath); // => [ 'images', 'logo.png' ] res.send(`File: ${req.params.filepath.join('/')}`);});import { type Request, type Response } from 'express';
app.get('/files/*filepath', (req: Request<{ filepath: string[] }>, res: Response) => { // GET /files/images/logo.png console.dir(req.params.filepath); // => [ 'images', 'logo.png' ] res.send(`File: ${req.params.filepath.join('/')}`);});Para também coincidir com o caminho raiz, envolva o caractere curinga nos chaves:
// Matches / , /foo , /foo/bar , etc.app.get('/{*splat}', (req, res) => { // GET / => req.params = {}, splat is omitted // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ] res.send('ok');});import { type Request, type Response } from 'express';
// Matches / , /foo , /foo/bar , etc.app.get('/{*splat}', (req: Request, res: Response) => { // GET / => req.params = {}, splat is omitted // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ] res.send('ok');});Segmentos opcionais
Use chaves para definir segmentos opcionais em um caminho de rota. Quando o segmento não está presente, o parâmetro é omitido de req.params.
app.get('/:file{.:ext}', (req, res) => { // GET /image.png => req.params = { file: 'image', ext: 'png' } // GET /image => req.params = { file: 'image' } res.send('ok');});import { type Request, type Response } from 'express';
app.get('/:file{.:ext}', (req: Request, res: Response) => { // GET /image.png => req.params = { file: 'image', ext: 'png' } // GET /image => req.params = { file: 'image' } res.send('ok');});The braces can also wrap a whole parameter to make it optional. Note that everything inside the braces is optional, so the position of the slash matters:
app.get('/user/{:id}', (req, res) => { // GET /user/42 => req.params = { id: '42' } // GET /user/ => req.params = {} // GET /user => 404, only the parameter is optional res.send('ok');});
app.get('/order{/:id}', (req, res) => { // GET /order/42 => req.params = { id: '42' } // GET /order => req.params = {}, the whole segment is optional res.send('ok');});import { type Request, type Response } from 'express';
app.get('/user/{:id}', (req: Request, res: Response) => { // GET /user/42 => req.params = { id: '42' } // GET /user/ => req.params = {} // GET /user => 404, only the parameter is optional res.send('ok');});
app.get('/order{/:id}', (req: Request, res: Response) => { // GET /order/42 => req.params = { id: '42' } // GET /order => req.params = {}, the whole segment is optional res.send('ok');});Não confunda a posição da barra no caminho da rota com a configuração strict routing, que diz respeito à URL da requisição: ela controla se uma URL terminada em barra que o caminho da rota não exige ainda corresponde. Por exemplo, uma requisição para /order/ corresponde à rota /order{/:id} por padrão, mas retorna um erro 404 quando o strict routing está habilitado; a barra final de /user/ não é afetada porque a rota /user/{:id} a exige. Todas as requisições comentadas nos exemplos acima se comportam da mesma forma independentemente dessa configuração.
Manipuladores de rota
Você pode fornecer várias funções de retorno de chamada que se comportam como middleware para lidar com uma solicitação. A única exceção é que esses callbacks podem invocar next('route') para ignorar as chamadas restantes da rota. Você pode usar este mecanismo para impor pré-condições em uma rota, então passe controle para rotas subsequentes se não houver motivo para prosseguir com a rota atual.
app.get('/user/:id', (req, res, next) => { if (req.params.id === '0') { return next('route'); } res.send(`User ${req.params.id}`);});
app.get('/user/:id', (req, res) => { res.send('Special handler for user ID 0');});import { type Request, type Response, type NextFunction } from 'express';
app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { if (req.params.id === '0') { return next('route'); } res.send(`User ${req.params.id}`);});
app.get('/user/:id', (req: Request, res: Response) => { res.send('Special handler for user ID 0');});Neste exemplo:
GET /user/5→ tratado pela primeira rota → envia “Usuário 5”GET /user/0→ primeira rota chamanext('route'), pulando para a próxima rota/user/:idcorrespondente
Os manipuladores de rotas podem estar na forma de uma função, um array de funções ou combinações de ambos, como mostrado nos exemplos a seguir.
Uma única função de retorno de chamada pode manipular uma rota. Por exemplo:
app.get('/example/a', (req, res) => { res.send('Hello from A!');});import { type Request, type Response } from 'express';
app.get('/example/a', (req: Request, res: Response) => { res.send('Hello from A!');});Mais de uma função de retorno de chamada pode manipular uma rota (certifique-se de especificar o objeto next). Por exemplo:
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!'); });import { type Request, type Response, type NextFunction } from 'express';
app.get( '/example/b', (req: Request, res: Response, next: NextFunction) => { console.log('the response will be sent by the next function ...'); next(); }, (req: Request, res: Response) => { res.send('Hello from B!'); });Um array de funções de retorno de chamada pode lidar com uma rota. Por exemplo:
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]);import { type Request, type Response, type NextFunction } from 'express';
const cb0 = function (req: Request, res: Response, next: NextFunction) { console.log('CB0'); next();};
const cb1 = function (req: Request, res: Response, next: NextFunction) { console.log('CB1'); next();};
const cb2 = function (req: Request, res: Response) { res.send('Hello from C!');};
app.get('/example/c', [cb0, cb1, cb2]);Uma combinação de funções independentes e matrizes de funções pode lidar com uma rota. Por exemplo:
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!'); });import { type Request, type Response, type NextFunction } from 'express';
const cb0 = function (req: Request, res: Response, next: NextFunction) { console.log('CB0'); next();};
const cb1 = function (req: Request, res: Response, next: NextFunction) { console.log('CB1'); next();};
app.get( '/example/d', [cb0, cb1], (req: Request, res: Response, next: NextFunction) => { console.log('the response will be sent by the next function ...'); next(); }, (req: Request, res: Response) => { res.send('Hello from D!'); });Métodos de resposta
The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. Se nenhum destes métodos for chamado de um manipulador de redes, a solicitação do cliente será deixada em suspenso.
| Método | Descrição: |
|---|---|
| res.download() | Solicite que um arquivo seja baixado. |
| res.end() | Encerrar o processo de resposta. |
| res.json() | Enviar uma resposta JSON. |
| res.jsonp() | Envie uma resposta JSON com suporte a JSONP. |
| res.redirect() | Redirecionar uma requisição. |
| res.render() | Renderizar um modelo de visão. |
| res.send() | Envie uma resposta de vários tipos. |
| res.sendFile() | Envia um arquivo como uma transmissão octet. |
| res.sendStatus() | Defina o código de status da resposta e envie sua representação de string como o corpo da resposta. |
app.route()
Você pode criar manipuladores de rotas em cadeia para um caminho de rota usando app.route().
Because the path is specified in a single location, this helps to create modular routes and reduces redundancy and typos. For more information about routes, see the Router() documentation.
Aqui está um exemplo de manipuladores de rota encadeados que são definidos usando 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'); });import { type Request, type Response } from 'express';
app .route('/book') .get((req: Request, res: Response) => { res.send('Get a random book'); }) .post((req: Request, res: Response) => { res.send('Add a book'); }) .put((req: Request, res: Response) => { res.send('Update the book'); });express.Router
Use a classe ‘express.Router’ para criar módulo, manipuladores de rotas montáveis. Uma instância Router é um sistema completo de middleware e roteamento; por este motivo, é muitas vezes referido como um “mini-app”.
O exemplo a seguir cria um roteador como um módulo, carrega uma função middleware nele define algumas rotas e monta o módulo do roteador em um caminho no aplicativo principal.
Crie um arquivo de roteador chamado birds.js no diretório de aplicativos, com o seguinte conteúdo:
const express = require('express');const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req, res, next) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req, res) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req, res) => { res.send('About birds');});
module.exports = router;import express from 'express';
const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req, res, next) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req, res) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req, res) => { res.send('About birds');});
export default router;import express, { type Request, type Response, type NextFunction } from 'express';
const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req: Request, res: Response, next: NextFunction) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req: Request, res: Response) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req: Request, res: Response) => { res.send('About birds');});
export default router;Em seguida, carregue o módulo do roteador no aplicativo:
const birds = require('./birds');
// ...
app.use('/birds', birds);import birds from './birds';
// ...
app.use('/birds', birds);O aplicativo agora poderá lidar com pedidos para /birds e /birds/about, Além de chamar a função middleware timeLog que é específica da rota.
Mas se a rota pai /birds tiver parâmetros de caminho, ela não será acessível por padrão nas sub-rotas. To make it accessible, you will need to pass the mergeParams option to the Router constructor.
const router = express.Router({ mergeParams: true });