como-hacer-un-servidor-nodejs

Cómo hacer un Servidor Web con Node.js y el módulo HTTP

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 github-full