Router

Un objeto router es una instancia de middleware y rutas. Puedes pensar en él como una “mini-aplicación,” capaz solo de realizar funciones de middleware y enrutamiento. Cada aplicación Express tiene un router de aplicación integrado.

Un router se comporta como middleware en sí mismo, así que puedes usarlo como argumento de app.use() o como argumento del método use() de otro router.

El objeto express de nivel superior tiene un método Router() que crea un nuevo objeto router.

Una vez que has creado un objeto router, puedes añadir middleware y rutas de métodos HTTP (como get, put, post, etc.) a él igual que en una aplicación. Por ejemplo:

// 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) => {
// ..
});

Puedes entonces usar un router para una URL raíz particular de esta forma, separando tus rutas en archivos o incluso mini-aplicaciones.

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

Métodos

Router()

Argumentos

options
Tipo: Object | undefined

Opciones que configuran el comportamiento del router.

caseSensitive
Tipo: Boolean Por defecto: false

Activa la sensibilidad a mayúsculas/minúsculas. Desactivado por defecto, tratando /Foo y /foo como iguales.

mergeParams
Tipo: Boolean Por defecto: false

Preserva los valores de req.params del router padre. Si el padre y el hijo tienen nombres de parámetros en conflicto, el valor del hijo tiene prioridad.

strict
Tipo: Boolean Por defecto: false

Habilita el enrutamiento estricto. Deshabilitado por defecto, /foo y /foo/ son tratados de la misma manera por el router.

Crea un nuevo objeto router.

index.cjs
const express = require('express');
const router = express.Router({ caseSensitive: true, strict: true });
router.get('/events', (req, res) => {
res.send('events');
});
// mount the router on an app
app.use('/calendar', router);

router.all()

Argumentos

path
Tipo: String | RegExp | Array

La ruta para la cual se invocan los callbacks de ruta.

callback
Tipo: Function | Function[]

Una o más funciones middleware/manejadoras. Cada una puede llamar a next('route') para saltar los callbacks restantes.

Este método es igual a los métodos router.METHOD(), excepto que coincide con todos los métodos HTTP (verbos).

Este método es extremadamente útil para mapear lógica “global” para prefijos de ruta específicos o coincidencias arbitrarias. Por ejemplo, si colocaras la siguiente ruta al principio de todas las demás definiciones de rutas, requeriría que todas las rutas a partir de ese punto requirieran autenticación, y cargaría automáticamente un usuario. Ten en cuenta que estos callbacks no tienen que actuar como puntos finales; loadUser puede realizar una tarea, luego llamar a next() para continuar coincidiendo con las rutas subsiguientes.

router.all('{*splat}', requireAuthentication, loadUser);

O el equivalente:

router.all('{*splat}', requireAuthentication);
router.all('{*splat}', loadUser);

Otro ejemplo de esto es la funcionalidad “global” con lista blanca. Aquí, el ejemplo es muy similar al anterior, pero solo restringe las rutas con el prefijo “/api”:

router.all('/api/{*splat}', requireAuthentication);

router.METHOD()

Argumentos

path
Tipo: String | RegExp | Array

La ruta para la cual se invocan los callbacks de ruta.

callback
Tipo: Function | Function[]

Una o más funciones middleware/manejadoras. Cada una puede llamar a next('route') para saltar los callbacks restantes.

Los métodos router.METHOD() proporcionan la funcionalidad de enrutamiento en Express, donde METHOD es uno de los métodos HTTP, como GET, PUT, POST, etc., en minúsculas. Por lo tanto, los métodos reales son router.get(), router.post(), router.put(), etc.

Nota

La función router.get() se llama automáticamente para el método HTTP HEAD además del método GET si router.head() no fue llamado para la ruta antes de router.get().

Nota

router.query() enruta peticiones HTTP QUERY, reflejando app.query(). El método QUERY está controlado por el runtime y requiere Node.js >=20.19.3 <21 || >=22.2.0.

Puedes proporcionar múltiples callbacks, y todos son tratados por igual, y se comportan como middleware, excepto que estos callbacks pueden invocar next('route') para omitir los callbacks de ruta restantes. Puedes usar este mecanismo para realizar pre-condiciones en una ruta y luego pasar el control a las rutas subsiguientes cuando no haya razón para continuar con la ruta coincidente.

El siguiente fragmento ilustra la definición de ruta más simple posible. Express traduce los strings de ruta a expresiones regulares, usadas internamente para coincidir con las peticiones entrantes. Los query strings no se consideran al realizar estas coincidencias, por ejemplo “GET /” coincidiría con la siguiente ruta, al igual que “GET /?name=tobi”.

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

También puedes usar expresiones regulares — útil si tienes restricciones muy específicas, por ejemplo lo siguiente coincidiría con “GET /commits/71dbb9c” así como con “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}`);
});

Puedes usar la primitiva next para implementar un control de flujo entre diferentes funciones de middleware, basándose en un estado específico del programa. Invocar next con el string 'router' causará que todos los callbacks de ruta restantes en ese router sean omitidos.

El siguiente ejemplo ilustra el uso de next('router').

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

router.param()

Argumentos

name
Tipo: String

El nombre del parámetro de ruta al que adjuntar el trigger. A diferencia de app.param(), esto no acepta un array.

callback
Tipo: Function

El trigger llamado como callback(req, res, next, value, name).

Añade disparadores de callback a los parámetros de ruta, donde name es el nombre del parámetro y callback es la función de callback. El parámetro name es obligatorio.

Los parámetros de la función de callback son:

  • req, el objeto de petición.
  • res, el objeto de respuesta.
  • next, indicando la siguiente función middleware.
  • El valor del parámetro name.
  • El nombre del parámetro.

Nota

A diferencia de app.param(), router.param() no acepta un array de parámetros de ruta.

Por ejemplo, cuando :user está presente en una ruta, puedes mapear lógica de carga de usuario para proporcionar automáticamente req.user a la ruta, o realizar validaciones sobre la entrada del parámetro.

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

Las funciones de callback de parámetros son locales al router en el que se definen. No son heredadas por apps o routers montados, ni se activan para parámetros de ruta heredados de routers padre. Por lo tanto, los callbacks de parámetros definidos en router solo se activarán por parámetros de ruta definidos en las rutas de router.

Un callback de parámetro se llamará solo una vez en un ciclo petición-respuesta, incluso si el parámetro coincide en múltiples rutas, como se muestra en los siguientes ejemplos.

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();
});

En GET /user/42, se imprime lo siguiente:

CALLED ONLY ONCE
although this matches
and this matches too

router.route()

Argumentos

path
Tipo: String

La ruta de la ruta a crear.

Devuelve una instancia de una sola ruta que puedes usar luego para manejar verbos HTTP con middleware opcional. Usa router.route() para evitar la duplicación de nombres de ruta y así errores de escritura.

Basándose en el ejemplo de router.param() anterior, el siguiente código muestra cómo usar router.route() para especificar varios manejadores de métodos 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'));
});

Este enfoque reutiliza la única ruta /users/:user_id y añade manejadores para varios métodos HTTP.

Nota

Cuando usas router.route(), el orden del middleware se basa en cuándo se crea la route, no en cuándo se añaden los manejadores de método a la ruta. Para este propósito, puedes considerar que los manejadores de método pertenecen a la ruta a la que fueron añadidos.

router.use()

Argumentos

path
Tipo: String | RegExp | Array | undefined

La ruta de montaje para el middleware. Por defecto es /.

callback
Tipo: Function | Function[]

Una o más funciones middleware a montar.

Usa la función o funciones middleware especificadas, con ruta de montaje opcional path, que por defecto es ”/”.

Este método es similar a app.use(). Un ejemplo simple y caso de uso se describe abajo. Consulta app.use() para más información.

El middleware es como una tubería de plomería: las peticiones empiezan en la primera función middleware definida y van bajando por la pila de middleware procesando cada ruta que coinciden.

index.cjs
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);

La ruta de “montaje” se elimina y no es visible para la función middleware. El efecto principal de esta característica es que una función middleware montada puede operar sin cambios de código independientemente de su nombre de ruta de “prefijo”.

El orden en que defines middleware con router.use() es muy importante. Se invocan secuencialmente, por lo tanto el orden define la precedencia del middleware. Por ejemplo, normalmente un logger es el primer middleware que usarías, para que cada petición quede registrada.

index.cjs
const logger = require('morgan');
router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use((req, res) => {
res.send('Hello');
});

Ahora supón que quisieras ignorar el registro de peticiones para archivos estáticos, pero continuar registrando rutas y middleware definidos después de logger(). Simplemente moverías la llamada a express.static() al principio, antes de añadir el middleware logger:

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

Otro ejemplo es servir archivos desde múltiples directorios, dando precedencia a ”./public” sobre los demás:

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

El método router.use() también soporta parámetros nombrados para que tus puntos de montaje para otros routers puedan beneficiarse de la precarga usando parámetros nombrados.

Nota

Aunque estas funciones middleware se añaden vía un router particular, cuándo se ejecutan se define por la ruta a la que están adjuntas (no el router). Por lo tanto, el middleware añadido vía un router puede ejecutarse para otros routers si sus rutas coinciden.

Por ejemplo, este código muestra dos routers diferentes montados en la misma ruta:

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);

A pesar de que el middleware de autenticación se añadió vía el authRouter se ejecutará también en las rutas definidas por el openRouter ya que ambos routers estaban montados en /users. Para evitar este comportamiento, usa rutas diferentes para cada router.