Node.js Enrutamiento

En Node.js, el enrutamiento es una parte clave del manejo de solicitudes HTTP; determina cómo distribuir las solicitudes según diferentes URLs y métodos HTTP (como GET, POST, PUT, DELETE, etc.).

El enrutamiento se utiliza generalmente para construir aplicaciones web, especialmente API RESTful.

Node.js en sí no tiene un mecanismo de enrutamiento integrado, pero se puede implementar mediante bibliotecas de middleware (como Express).

El enrutamiento generalmente involucra los siguientes aspectos:

  • Coincidencia de URL: hace coincidir las reglas de ruta según la URL de la solicitud.
  • Coincidencia de métodos HTTP: hace coincidir las reglas de ruta según el método HTTP de la solicitud (GET, POST, PUT, DELETE, etc.).
  • Manejo de solicitudes: una vez que se encuentra una regla de ruta adecuada, se llama a la función de manejo correspondiente para procesar la solicitud.

En Node.js, podemos crear un enrutamiento simple mediante el módulo http, como en el siguiente ejemplo:

Ejemplo

const http = require('http');

// Crear el servidor y definir las rutas
const server = http.createServer((req, res) => {
  const { url, method } = req;

  if (url === '/' && method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Home Page');
  } else if (url === '/about' && method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('About Page');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('404 Not Found');
  }
});

server.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});

Acceso desde el navegadorhttp://localhost:3000Muestra lo siguiente:

Acceso desde el navegadorhttp://localhost:3000/aboutMuestra lo siguiente:

Si accede a otras direcciones URL, se mostrará directamente404 Not Found。

Para más solicitudes HTTP, consulte:Tutorial de HTTP。


Parámetros de solicitud

Una URL completahttp://localhost:8888/start?foo=bar&hello=worldincluye el host, la ruta y la cadena de consulta.

Para analizar estos datos, podemos usar elURLobjeto y elquerystringmódulo.

const myUrl = new URL("http://localhost:8888/start?foo=bar&hello=world");

// 提取路径名
console.log(myUrl.pathname); // 输出: /start

// 提取查询参数
console.log(myUrl.searchParams.get("foo"));   // 输出: bar
console.log(myUrl.searchParams.get("hello")); // 输出: world
myUrl.pathname
          |
          |
        -----
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
           myUrl.searchParams.get("foo")    |
                                            |
                                     myUrl.searchParams.get("hello")

Por supuesto, también podemos usar el módulo querystring para analizar los parámetros en el cuerpo de las solicitudes POST. El contenido relacionado,Solicitudes GET/POST de Node.js,se presentará más adelante.

Todos los datos de solicitud que necesitamos estarán contenidos en el objeto request, que se pasa como primer parámetro de la función de devolución de llamada onRequest().

Ahora agreguemos algo de lógica a la función onRequest() del módulo http para averiguar la ruta de la URL solicitada por el navegador:

Código del archivo server.js:

var http = require("http"); var url = require("url"); function start() { function onRequest(request, response) { //Usar el constructor URL para analizar la ruta de la solicitud const pathname = new URL(request.url, `http://${request.headers.host}`).pathname; console.log(`Request for ${pathname} received.`); //Imprimir la ruta de la solicitud //Configurar el encabezado y el contenido de la respuesta response.writeHead(200, { "Content-Type": "text/plain" }); //Configurar el código de estado y el tipo de contenido response.write("Hello World"); //Enviar el contenido de la respuesta al cliente response.end(); //Finalizar la respuesta } //Crear el servidor y escuchar en el puerto especificado http.createServer(onRequest).listen(8888); console.log("Server has started."); //Imprimir el mensaje de inicio del servidor } //Exportar la función start para que la usen otros módulos module.exports.start = start;

Bien, nuestra aplicación ahora puede distinguir diferentes solicitudes según la ruta de la URL solicitada; esto nos permite usar el enrutamiento (aún no completado) para mapear las solicitudes a los manejadores según la ruta de la URL.

En la aplicación que vamos a construir, esto significa que las solicitudes de /start y /upload se pueden manejar con código diferente. Más adelante veremos cómo se integran estas partes.

Ahora podemos escribir el enrutamiento. Creemos un archivo llamadorouter.jsy agreguemos el siguiente contenido:

Código del archivo router.js:

function route(pathname) { console.log("About to route a request for " + pathname); } //Se exporta la función route exports.route = route;

router.js maneja la lógica de enrutamiento; define y exporta la función route, que se utiliza para manejar diferentes rutas cuando el servidor recibe una solicitud.

Nuestro servidor debe saber que el enrutamiento existe y utilizarlo de manera efectiva. Por supuesto, podríamos vincular esta dependencia al servidor mediante codificación fija (hardcoding), pero la experiencia de programación en otros idiomas nos dice que esto sería muy doloroso, por lo que usaremos la inyección de dependencias para agregar el módulo de enrutamiento de manera más flexible.

Primero, extendamos la función start() del servidor para pasar la función de enrutamiento como parámetro.server.jsEl código del archivo es el siguiente:

Código del archivo server.js:

// server.js const http = require("http"); //Importar el módulo http de Node.js para crear el servidor const { URL } = require("url"); //Importar el constructor URL desde el módulo url //Definir y exportar la función start para iniciar el servidor function start(route) { //Definir la función onRequest para manejar cada solicitud function onRequest(request, response) { //Usar el constructor URL para analizar la ruta de la solicitud const pathname = new URL(request.url, `http://${request.headers.host}`).pathname; console.log(`Request for ${pathname} received.`); //Imprimir la ruta de la solicitud route(pathname); //Llamar a la función de enrutamiento para manejar la ruta //Configurar el encabezado y el contenido de la respuesta response.writeHead(200, { "Content-Type": "text/plain" }); response.write("Hello World"); response.end(); } //Crear el servidor y escuchar en el puerto especificado http.createServer(onRequest).listen(8888); console.log("Server has started."); } //Exportar la función start para que la usen otros módulos module.exports.start = start;

server.js define la lógica de inicio del servidor y llama a la función de enrutamiento cuando recibe una solicitud.

Al mismo tiempo, ampliaremos index.js en consecuencia para que la función de enrutamiento pueda inyectarse en el servidor:

Código del archivo index.js:

var server = require("./server"); var router = require("./router"); server.start(router.route);

index.js es el archivo de entrada del programa; se encarga de iniciar el servidor y pasar el módulo de enrutamiento al módulo del servidor.

Ahora inicie la aplicación (node index.js, recuerde siempre esta línea de comando) y luego solicite una URL; verá que la aplicación genera la información correspondiente. Esto indica que nuestro servidor HTTP ya está usando el módulo de enrutamiento y pasa la ruta de la solicitud al enrutador:

$ node index.js
Server has started.

Al acceder en el navegador ahttp://localhost:8888/, el servidor debería imprimir en la consola el mensaje de ruta correspondiente y devolver una respuesta 'Hello World':

El terminal en segundo plano mostrará la información de acceso:

Request for / received.
About to route a request for /
Request for /favicon.ico received.
About to route a request for /favicon.ico

Enrutamiento con Express

Express es un framework popular de Node.js que ofrece potentes funciones de enrutamiento.

Para obtener más contenido sobre Express, consulte:Framework Express de Node.js。

Instalación de Express

Primero, asegúrese de tener Express instalado. Si aún no lo ha instalado, puede usar npm para instalarlo:

npm install express

Enrutamiento básico

A continuación se muestra una aplicación Express simple que demuestra cómo configurar rutas básicas:

Ejemplo

const express = require('express');
const app = express();
const port = 3000;

// Definir una ruta GET
app.get('/', (req, res) => {
    res.send('Hello, World!');
});

// Definir una ruta POST
app.post('/submit', (req, res) => {
    res.send('Form submitted!');
});

// Iniciar el servidor
app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

Enrutamiento dinámico

El enrutamiento dinámico le permite usar URLs parametrizadas.

Por ejemplo, puede definir una ruta para manejar/users/:id, donde:ides un parámetro dinámico.

app.get('/users/:id', (req, res) => {
    const userId = req.params.id;
    res.send(`User ID: ${userId}`);
});

Parámetros de ruta

Express le permite extraer parámetros de la URL y acceder a ellos a través del objeto req.params.

Ejemplo

app.get('/users/:id', (req, res) => {
    const userId = req.params.id;
    res.send(`User ID: ${userId}`);
});

app.get('/search/:query', (req, res) => {
    const query = req.params.query;
    res.send(`Search query: ${query}`);
});

Parámetros de consulta

Los parámetros de consulta son pares clave-valor en la URL, generalmente se usan para transmitir información adicional. Puede acceder a los parámetros de consulta a través del objeto req.query.

app.get('/search', (req, res) => {
    const query = req.query.q;
    res.send(`Search query: ${query}`);
});

Middleware de ruta

El middleware de ruta es una función que se ejecuta antes o después de procesar la solicitud. Puede usar middleware para tareas como autenticación, registro de registros (logging), etc.

// 日志记录中间件
const logger = (req, res, next) => {
    console.log(`Request Type: ${req.method} ${req.url}`);
    next();
};

// 使用中间件
app.use(logger);

app.get('/', (req, res) => {
    res.send('Hello, World!');
});

Agrupación de rutas

Para organizar mejor el código, puede usar la agrupación de rutas. Express proporciona el objeto express.Router, que se puede usar para crear manejadores de rutas modulares y montables.

Ejemplo

const express = require('express');
const app = express();
const port = 3000;

// Crear una instancia del enrutador
const userRouter = express.Router();

// Definir rutas relacionadas con el usuario
userRouter.get('/', (req, res) => {
    res.send('List of users');
});

userRouter.get('/:id', (req, res) => {
    const userId = req.params.id;
    res.send(`User ID: ${userId}`);
});

// Montar el enrutador de usuarios
app.use('/users', userRouter);

// Iniciar el servidor
app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

Técnicas avanzadas de enrutamiento

1. Manejo de errores:Puede definir middleware de manejo de errores para capturar y procesar errores en las rutas.

app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

2. Prioridad de rutas:El orden de definición de las rutas determina su prioridad; las rutas definidas primero se emparejan primero.

3. Restricción de rutas:Puede usar middleware para restringir el acceso a ciertas rutas, por ejemplo, permitir solo el acceso a usuarios autenticados.

Ejemplo

const authMiddleware = (req, res, next) => {
    if (req.headers.authorization) {
        next();
    } else {
        res.status(401).send('Unauthorized');
    }
};

app.get('/admin', authMiddleware, (req, res) => {
    res.send('Admin page');
});
Otras extensiones