Node.js proporciona el módulo HTTP que nos permite crear servidores web de manera sencilla sin necesidad depender de librerías o frameworks externos.
Un servidor HTTP es una, básicamente, un programa que está siempre encendido y escucha constantemente peticiones de otros ordenados (a los que llamaremos clientes).
Cuando un cliente solicita una página web el servidor HTTP recibe esa solicitud y la procesa, devolviendo la página web solicitada al cliente.
Los servidores HTTP son necesarios para que “funcione Internet”. Crear servidores HTTP es uno de los propósitos principales de Node.js. Por lo que, os imaginaréis, lo hace bastante bien 😉.
En muchas ocasiones usaremos algún tipo de framework o librería para crear un servidor HTTP con Node.js. Sin embargo, tenemos disponible el módulo nativo HTTP que nos permite realizar la mayoría de proyectos básicos o intermedios.
Ejemplos de uso del módulo HTTP
Servidor HTTP básico
Este código crea un servidor HTTP básico que responde con “Hello World!” cuando se accede a él desde un navegador.
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World!\n');
});
// starts a simple http server locally on port 3000
server.listen(3000, '127.0.0.1', () => {
console.log('Listening on 127.0.0.1:3000');
});
Servidor HTTP con una página HTML
Este ejemplo crea un servidor HTTP que sirve una página HTML muy (muy) básica cuando se accede a él.
import { createServer } from 'node:http';
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>Simple Page</title>
</head>
<body>
<h1>Hello from Node.js!</h1>
</body>
</html>
`);
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
Este código crea un servidor HTTP que devuelve una página HTML con un título y un encabezado “Hello from Node.js!” cuando se accede a http://127.0.0.1:3000/
.
API REST básica
Este ejemplo muestra cómo crear un servidor HTTP que maneja diferentes rutas para una API REST básica.
import { createServer } from 'node:http';
const server = createServer((req, res) => {
const { method, url } = req;
if (method === 'GET' && url === '/api/users') {
// Simulando una base de datos de usuarios
const users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
];
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(users));
} else if (method === 'POST' && url === '/api/users') {
let body = '';
req.on('data', (chunk) => {
body += chunk.toString();
});
req.on('end', () => {
const newUser = JSON.parse(body);
// Aquí podrías guardar el nuevo usuario en la base de datos
res.writeHead(201, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'User added', user: newUser }));
});
} else {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Route not found' }));
}
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
En este ejemplo:
- Al hacer una solicitud
GET
a/api/users
, se devuelve una lista de usuarios en formato JSON. - Al hacer una solicitud
POST
a/api/users
, se espera un cuerpo JSON con los datos del nuevo usuario. Este usuario simulado se agregaría a una base de datos (simulado aquí) y se devuelve un mensaje de éxito junto con los detalles del nuevo usuario. - Cualquier otra ruta dará como resultado un mensaje de “Route not found” con un código de estado 404.
Servidor de archivos estáticos
Este ejemplo muestra cómo servir archivos estáticos, como archivos HTML, CSS, e imágenes desde un directorio específico.
import { createServer } from 'node:http';
import { readFile } from 'node:fs';
import { extname, join } from 'node:path';
const server = createServer((req, res) => {
let filePath = req.url === '/' ? '/index.html' : req.url;
const ext = extname(filePath);
const contentType = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'text/javascript',
'.png': 'image/png',
'.jpg': 'image/jpeg',
}[ext] || 'application/octet-stream';
filePath = join(__dirname, 'public', filePath);
readFile(filePath, (err, content) => {
if (err) {
if (err.code === 'ENOENT') {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 Not Found</h1>');
} else {
res.writeHead(500, { 'Content-Type': 'text/html' });
res.end('<h1>500 Internal Server Error</h1>');
}
} else {
res.writeHead(200, { 'Content-Type': contentType });
res.end(content);
}
});
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
Este ejemplo:
- Define un objeto
contentType
que mapea las extensiones de archivo a tipos MIME para servir diferentes tipos de archivos. - Lee el archivo solicitado desde un directorio
public
. - Maneja errores como archivos no encontrados (404) o errores internos del servidor (500).
- Sirve el contenido del archivo solicitado con el tipo MIME adecuado.
Descarga el código
Todo el código de esta entrada está disponible para su descarga en Github