certmundo.
es‑mx

6 min de lectura

¿Cómo crear un servidor HTTP con Node.js?

Un servidor HTTP con Node.js se crea usando el módulo nativo http, sin necesidad de instalar ningún paquete externo.

Imagina que abres una tienda en línea

Piensa en una tienda como Liverpool. Cuando un cliente llega, alguien en la entrada lo recibe y lo dirige al área correcta. Tu servidor HTTP funciona igual. Recibe peticiones de los navegadores y responde con la información adecuada. Sin un servidor, tu aplicación no puede hablar con el mundo exterior.

En esta lección vas a construir ese "recepcionista digital" desde cero, usando solo Node.js.

El Modelo Petición-Respuesta

Antes de escribir código, entiende el ciclo fundamental. Este ciclo tiene un nombre: el Modelo Petición-Respuesta (Request-Response).

Funciona así:

  1. El navegador envía una petición (request) a una dirección, por ejemplo http://localhost:3000.
  2. Tu servidor recibe esa petición y la analiza.
  3. El servidor envía una respuesta (response) con datos: texto, JSON, HTML, etc.

Todo servidor web del planeta opera bajo este mismo modelo. Node.js solo te da las herramientas para implementarlo en JavaScript.

Tu primer servidor HTTP en 8 líneas

Crea un archivo llamado servidor.js en tu proyecto. Escribe esto:

const http = require('http');

const servidor = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('¡Bienvenido a mi servidor Node.js!');
});

servidor.listen(3000, () => {
  console.log('Servidor corriendo en http://localhost:3000');
});

Ejecútalo en tu terminal:

node servidor.js

Abre tu navegador y visita http://localhost:3000. Verás el mensaje en pantalla. Acabas de crear tu primer servidor web.

¿Qué hace cada línea?

Vamos parte por parte, sin saltarnos nada.

require('http') importa el módulo nativo de Node.js para trabajar con HTTP. No necesitas npm install porque ya viene incluido en Node.

http.createServer((req, res) => { ... }) crea el servidor. Cada vez que alguien hace una petición, Node.js ejecuta esta función. Los parámetros req y res son objetos clave:

  • req (request): contiene toda la información de la petición. La URL que pidió el cliente, el método (GET, POST), los encabezados, etc.
  • res (response): es el objeto que usas para construir y enviar la respuesta.

res.writeHead(200, { 'Content-Type': 'text/plain' }) envía el encabezado HTTP. El 200 es el código de estado que significa "todo salió bien". El Content-Type le dice al navegador qué tipo de contenido recibirá.

res.end('...') envía el cuerpo de la respuesta y cierra la conexión. Sin esta línea, el navegador se quedaría esperando para siempre.

servidor.listen(3000, ...) indica que el servidor debe escuchar peticiones en el puerto 3000 de tu máquina.

Manejo de rutas básicas

Un servidor real no responde lo mismo a todas las URLs. Si trabajaras en el equipo de backend de Mercado Libre, /productos devolvería una lista de artículos y /usuarios devolvería información de cuentas. Necesitas rutas.

Usa la propiedad req.url para leer qué ruta pidió el cliente:

const http = require('http');

const servidor = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });

  if (req.url === '/') {
    res.end('Página de inicio');
  } else if (req.url === '/productos') {
    res.end('Lista de productos');
  } else if (req.url === '/contacto') {
    res.end('Página de contacto');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Página no encontrada');
  }
});

servidor.listen(3000, () => {
  console.log('Servidor corriendo en http://localhost:3000');
});

Ahora tu servidor responde de forma diferente según la ruta. Visita http://localhost:3000/productos y verás "Lista de productos". Visita una ruta que no existe y recibirás el código 404.

Responder con JSON

Las APIs modernas no devuelven texto plano. Devuelven JSON, un formato que entienden tanto los navegadores como las aplicaciones móviles. Imagina que el equipo de FEMSA necesita una API interna para consultar precios de sus productos en tiendas OXXO.

Así devuelves JSON desde tu servidor:

const http = require('http');

const productos = [
  { id: 1, nombre: 'Coca-Cola 600ml', precio: 18 },
  { id: 2, nombre: 'Agua Ciel 1L', precio: 12 },
  { id: 3, nombre: 'Sabritas Original', precio: 22 }
];

const servidor = http.createServer((req, res) => {
  if (req.url === '/api/productos') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(productos));
  } else {
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Ruta no encontrada' }));
  }
});

servidor.listen(3000, () => {
  console.log('Servidor corriendo en http://localhost:3000');
});

Dos cambios importantes aquí:

  • Content-Type cambia a application/json para que el cliente sepa que recibirá JSON.
  • JSON.stringify() convierte el arreglo de JavaScript a texto JSON válido antes de enviarlo.

Visita http://localhost:3000/api/productos y verás los datos en formato JSON directamente en el navegador.

Leer el método HTTP de la petición

No todas las peticiones son iguales. Hay varios métodos HTTP, y cada uno tiene un propósito:

Método Uso típico
GET Leer datos
POST Crear datos
PUT Actualizar datos
DELETE Eliminar datos

Puedes leer el método con req.method:

if (req.url === '/api/pedidos' && req.method === 'GET') {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ pedidos: [] }));
} else if (req.url === '/api/pedidos' && req.method === 'POST') {
  res.writeHead(201, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ mensaje: 'Pedido creado correctamente' }));
}

Este patrón es la base de cualquier API REST. Con req.url y req.method puedes construir endpoints completos.

Errores comunes al crear servidores

Varios errores aparecen casi siempre la primera vez. Conócelos antes de tropezar con ellos.

Error: listen EADDRINUSE: address already in use :::3000 Significa que el puerto 3000 ya está ocupado. Otro proceso lo está usando, probablemente una instancia anterior de tu servidor que no cerraste. Detén el proceso con Ctrl + C y vuelve a ejecutar tu archivo.

El navegador muestra la página en blanco o se cuelga Olvidaste llamar a res.end(). Sin esa línea, el servidor nunca cierra la conexión y el navegador espera indefinidamente.

Ves el JSON como texto sin formato raro Olvidaste cambiar el Content-Type a application/json. El navegador muestra los datos de forma diferente según el tipo de contenido declarado.

El servidor no detecta cambios en tu código Node.js no recarga el servidor automáticamente cuando modificas un archivo. Cada vez que cambies algo, detén el servidor con Ctrl + C y ejecútalo de nuevo. En la lección siguiente aprenderás a usar nodemon para automatizar esto.

Prueba tu servidor con diferentes rutas

Aquí tienes un ejercicio práctico. Crea un servidor que simule parte del backend de una tienda como Bimbo. El servidor debe responder a estas tres rutas:

  • GET / → mensaje de bienvenida con el nombre de la empresa.
  • GET /api/productos → arreglo JSON con al menos tres productos y sus precios.
  • Cualquier otra ruta → código 404 con un mensaje de error en JSON.

Prueba cada ruta en tu navegador. Después intenta acceder a /api/usuarios o cualquier ruta que no existe y verifica que recibes el 404 correcto.

Este ejercicio cubre exactamente lo que necesitas para construir APIs básicas desde cero.

El servidor HTTP es el corazón de tu backend

Todo lo que construirás en Node.js empieza aquí. Los frameworks como Express.js, que verás más adelante, en realidad usan este mismo módulo http por debajo. Aprenderlo directamente te da una ventaja enorme: entiendes qué pasa realmente, sin depender de magia invisible.

El módulo http de Node.js es suficiente para construir una API funcional; los frameworks solo la hacen más cómoda de mantener.

Puntos clave

  • El módulo nativo `http` de Node.js te permite crear un servidor web completo sin instalar ningún paquete externo. Usa `http.createServer()` y `servidor.listen(puerto)` para ponerlo en marcha.
  • Cada petición activa una función con dos objetos clave: `req` (información de la petición, como `req.url` y `req.method`) y `res` (herramientas para construir la respuesta con `res.writeHead()` y `res.end()`).
  • Para manejar rutas básicas, usa condicionales sobre `req.url`. Responde con código `200` cuando la ruta existe y con `404` cuando no. Siempre llama a `res.end()` o el navegador se quedará esperando.
  • Cuando devuelvas JSON, cambia el encabezado `Content-Type` a `application/json` y convierte tus datos con `JSON.stringify()` antes de pasarlos a `res.end()`.
  • Si ves el error `EADDRINUSE`, el puerto ya está ocupado. Detén el proceso anterior con `Ctrl + C` y vuelve a ejecutar tu servidor.

Comparte esta lección:

¿Cómo crear un servidor HTTP con Node.js? | Node.js Básico: Backend con JavaScript | Certmundo