Express

Express

Tutorial Express: Request y Response

Aprende a manejar los objetos Request y Response en Express para controlar solicitudes y respuestas HTTP en tus aplicaciones web.

Aprende Express y certifícate

Objeto Request (req)

El objeto Request representa la solicitud HTTP que recibe tu aplicación Express. Este objeto contiene toda la información que el cliente envía al servidor, desde los datos de la URL hasta los headers y el cuerpo de la petición.

Express enriquece el objeto request nativo de Node.js añadiendo propiedades y métodos específicos que facilitan el manejo de las solicitudes web. Cada vez que se ejecuta una función de ruta, Express pasa automáticamente este objeto como primer parámetro.

Propiedades fundamentales del objeto Request

La propiedad req.url contiene la ruta completa de la solicitud, incluyendo la query string si existe:

app.get('/usuarios', (req, res) => {
  console.log(req.url); // '/usuarios' o '/usuarios?page=1'
});

Para acceder únicamente a la ruta sin parámetros, utiliza req.path:

app.get('/productos', (req, res) => {
  console.log(req.path); // '/productos' (sin query string)
  console.log(req.url);  // '/productos?categoria=electronica'
});

El método HTTP se obtiene mediante req.method:

app.all('/api/datos', (req, res) => {
  console.log(`Método utilizado: ${req.method}`); // GET, POST, PUT, etc.
});

Acceso a parámetros de ruta

Los parámetros dinámicos definidos en las rutas se acceden a través de req.params:

app.get('/usuarios/:id', (req, res) => {
  const userId = req.params.id;
  console.log(`ID del usuario: ${userId}`);
});

app.get('/productos/:categoria/:id', (req, res) => {
  const { categoria, id } = req.params;
  console.log(`Categoría: ${categoria}, ID: ${id}`);
});

Manejo de query parameters

Los parámetros de consulta (query string) están disponibles en req.query como un objeto:

app.get('/buscar', (req, res) => {
  const { termino, limite, pagina } = req.query;
  console.log('Término de búsqueda:', termino);
  console.log('Límite:', limite || 10);
  console.log('Página:', pagina || 1);
});

// GET /buscar?termino=javascript&limite=20&pagina=2

Headers de la solicitud

Los headers HTTP se acceden mediante req.headers o el método req.get():

app.get('/info', (req, res) => {
  // Acceso directo al objeto headers
  console.log(req.headers['user-agent']);
  console.log(req.headers.authorization);
  
  // Método get() (insensible a mayúsculas)
  console.log(req.get('Content-Type'));
  console.log(req.get('Accept'));
});

Información del cliente

Express proporciona información útil sobre el cliente que realiza la solicitud:

app.get('/cliente-info', (req, res) => {
  console.log('IP del cliente:', req.ip);
  console.log('IPs (si hay proxies):', req.ips);
  console.log('Protocolo:', req.protocol); // 'http' o 'https'
  console.log('Subdominio:', req.subdomains);
});

Acceso al cuerpo de la solicitud

Para solicitudes POST, PUT o PATCH, el cuerpo se encuentra en req.body. Es importante configurar el middleware adecuado para parsear el contenido:

// Configuración para JSON
app.use(express.json());

// Configuración para formularios
app.use(express.urlencoded({ extended: true }));

app.post('/usuarios', (req, res) => {
  const { nombre, email, edad } = req.body;
  console.log('Datos recibidos:', { nombre, email, edad });
});

Detección del tipo de contenido

El método req.is() permite verificar el tipo de contenido de la solicitud:

app.post('/upload', (req, res) => {
  if (req.is('application/json')) {
    console.log('Contenido JSON recibido');
  } else if (req.is('multipart/form-data')) {
    console.log('Formulario con archivos');
  } else if (req.is('text/*')) {
    console.log('Contenido de texto');
  }
});

Cookies y sesiones

Las cookies enviadas por el cliente están disponibles en req.cookies (requiere el middleware cookie-parser):

app.get('/perfil', (req, res) => {
  const sessionId = req.cookies.sessionId;
  const preferences = req.cookies.userPrefs;
  console.log('Session ID:', sessionId);
  console.log('Preferencias:', preferences);
});

Ejemplo práctico completo

Un ejemplo que combina múltiples propiedades del objeto request:

app.get('/api/productos/:categoria', (req, res) => {
  // Parámetros de ruta
  const categoria = req.params.categoria;
  
  // Query parameters
  const { limite = 10, orden = 'nombre', filtro } = req.query;
  
  // Headers
  const userAgent = req.get('User-Agent');
  const acceptLanguage = req.get('Accept-Language');
  
  // Información de la solicitud
  console.log(`Solicitud ${req.method} desde ${req.ip}`);
  console.log(`Categoría: ${categoria}`);
  console.log(`Límite: ${limite}, Orden: ${orden}`);
  
  if (filtro) {
    console.log(`Filtro aplicado: ${filtro}`);
  }
  
  // Lógica de negocio basada en los datos del request
  const productos = obtenerProductos(categoria, { limite, orden, filtro });
  
  res.json(productos);
});

El objeto request es fundamental para el routing ya que proporciona toda la información necesaria para procesar las solicitudes de manera dinámica y contextual, permitiendo que las rutas respondan de forma inteligente según los datos enviados por el cliente.

Objeto Response (res)

El objeto Response representa la respuesta HTTP que tu aplicación Express enviará de vuelta al cliente. Este objeto proporciona métodos y propiedades para configurar y enviar datos, establecer headers, códigos de estado y controlar cómo se entrega la respuesta al navegador o cliente que realizó la solicitud.

Express extiende el objeto response nativo de Node.js con métodos específicos que simplifican enormemente el proceso de construcción y envío de respuestas HTTP. Cada función de ruta recibe automáticamente este objeto como segundo parámetro.

Envío de respuestas básicas

El método res.send() es la forma más versátil de enviar una respuesta, ya que detecta automáticamente el tipo de contenido:

app.get('/texto', (req, res) => {
  res.send('Hola mundo'); // Content-Type: text/html
});

app.get('/numero', (req, res) => {
  res.send(404); // Envía el número como código de estado
});

app.get('/objeto', (req, res) => {
  res.send({ mensaje: 'Datos del servidor' }); // Content-Type: application/json
});

Para respuestas JSON específicas, utiliza res.json():

app.get('/api/usuario', (req, res) => {
  const usuario = {
    id: 1,
    nombre: 'Ana García',
    email: 'ana@ejemplo.com'
  };
  res.json(usuario);
});

Configuración de códigos de estado

El código de estado HTTP se establece mediante res.status(), que se puede encadenar con otros métodos:

app.post('/api/usuarios', (req, res) => {
  // Recurso creado exitosamente
  res.status(201).json({ 
    mensaje: 'Usuario creado',
    id: 123 
  });
});

app.get('/api/usuarios/:id', (req, res) => {
  const usuario = buscarUsuario(req.params.id);
  
  if (!usuario) {
    return res.status(404).json({ 
      error: 'Usuario no encontrado' 
    });
  }
  
  res.json(usuario);
});

Gestión de headers de respuesta

Los headers HTTP se configuran con res.set() o res.header():

app.get('/api/datos', (req, res) => {
  // Establecer un header individual
  res.set('X-API-Version', '1.0');
  
  // Establecer múltiples headers
  res.set({
    'Cache-Control': 'no-cache',
    'X-Powered-By': 'Express 5'
  });
  
  res.json({ datos: 'información importante' });
});

Para headers específicos existen métodos dedicados:

app.get('/descarga', (req, res) => {
  res.type('application/pdf');
  res.attachment('documento.pdf');
  // Lógica para enviar el archivo
});

Redirecciones

El método res.redirect() envía una respuesta de redirección al cliente:

app.get('/admin', (req, res) => {
  if (!usuarioAutenticado(req)) {
    return res.redirect('/login');
  }
  res.send('Panel de administración');
});

app.post('/procesar-formulario', (req, res) => {
  // Procesar datos del formulario
  procesarDatos(req.body);
  
  // Redirección con código de estado específico
  res.redirect(303, '/confirmacion');
});

Envío de archivos

Para servir archivos estáticos, Express proporciona res.sendFile():

app.get('/documento/:nombre', (req, res) => {
  const nombreArchivo = req.params.nombre;
  const rutaCompleta = path.join(__dirname, 'documentos', nombreArchivo);
  
  res.sendFile(rutaCompleta, (err) => {
    if (err) {
      res.status(404).send('Archivo no encontrado');
    }
  });
});

El método res.download() fuerza la descarga del archivo:

app.get('/descargar/:archivo', (req, res) => {
  const archivo = req.params.archivo;
  const ruta = path.join(__dirname, 'descargas', archivo);
  
  // Descarga con nombre personalizado
  res.download(ruta, `backup-${archivo}`, (err) => {
    if (err) {
      res.status(500).send('Error en la descarga');
    }
  });
});

Gestión de cookies

Las cookies se establecen mediante res.cookie():

app.post('/login', (req, res) => {
  // Validar credenciales
  if (credencialesValidas(req.body)) {
    // Cookie simple
    res.cookie('sessionId', generarSessionId());
    
    // Cookie con opciones
    res.cookie('userPrefs', JSON.stringify(preferencias), {
      maxAge: 24 * 60 * 60 * 1000, // 24 horas
      httpOnly: true,
      secure: true
    });
    
    res.json({ mensaje: 'Login exitoso' });
  } else {
    res.status(401).json({ error: 'Credenciales inválidas' });
  }
});

Para eliminar cookies, utiliza res.clearCookie():

app.post('/logout', (req, res) => {
  res.clearCookie('sessionId');
  res.clearCookie('userPrefs');
  res.json({ mensaje: 'Sesión cerrada' });
});

Renderizado de vistas

Si utilizas un motor de plantillas, res.render() procesa y envía las vistas:

app.get('/perfil/:id', (req, res) => {
  const usuario = obtenerUsuario(req.params.id);
  
  res.render('perfil', {
    titulo: 'Perfil de Usuario',
    usuario: usuario,
    fechaActual: new Date()
  });
});

Control de finalización de respuesta

El método res.end() finaliza la respuesta sin enviar datos adicionales:

app.get('/ping', (req, res) => {
  res.status(200);
  res.set('X-Response-Time', Date.now());
  res.end(); // Respuesta vacía con headers
});

Ejemplo práctico de API REST

Un ejemplo que combina múltiples métodos del objeto response:

app.put('/api/productos/:id', (req, res) => {
  const productId = req.params.id;
  const datosActualizacion = req.body;
  
  // Validar datos
  if (!datosActualizacion.nombre || !datosActualizacion.precio) {
    return res.status(400).json({
      error: 'Faltan campos obligatorios',
      campos: ['nombre', 'precio']
    });
  }
  
  // Buscar producto
  const producto = buscarProducto(productId);
  if (!producto) {
    return res.status(404).json({
      error: 'Producto no encontrado'
    });
  }
  
  // Actualizar producto
  const productoActualizado = actualizarProducto(productId, datosActualizacion);
  
  // Configurar headers de respuesta
  res.set({
    'Last-Modified': new Date().toISOString(),
    'X-Resource-Version': productoActualizado.version
  });
  
  // Enviar respuesta exitosa
  res.status(200).json({
    mensaje: 'Producto actualizado correctamente',
    producto: productoActualizado
  });
});

El objeto response es esencial para el routing ya que determina exactamente qué información, formato y metadatos recibe el cliente, permitiendo crear APIs robustas y aplicaciones web que respondan de manera apropiada a cada tipo de solicitud.

Aprende Express online

Otras lecciones de Express

Accede a todas las lecciones de Express y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Express y certifícate

Ejercicios de programación de Express

Evalúa tus conocimientos de esta lección Request y Response con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.