Discriminar rutas y devolver respuestas correctas en Node.js
Hasta ahora tenemos un servidor Node.js escuchando correctamente, pero con una limitación importante: responde lo mismo en cualquier ruta. Da igual si accedemos a /, /usuarios o cualquier otra URL.
En esta clase vamos a aprender a discriminar rutas, devolver respuestas distintas según la URL, manejar correctamente los status codes y enviar JSON bien formado. Estos son los cimientos de cómo funcionan los frameworks modernos.
El problema: todas las rutas responden igual
Si no controlamos la ruta, nuestro servidor se comporta de forma monótona:
- Responde siempre lo mismo independientemente de la intención del usuario.
- No diferencia entre recursos (ej.
/vs/usuarios). - No puede devolver errores de forma semántica (como un 404).
Esto es justo lo que queremos evitar en un backend profesional.
Discriminando rutas con la URL
Node.js nos permite acceder a la URL de la petición a través del objeto req.url. Con esta información, podemos decidir qué lógica ejecutar en cada caso.
import http from 'node:http'
const server = http.createServer((req, res) => {
const { url } = req
if (url === '/') {
res.end('<h1>Bienvenido a la Home</h1>')
} else if (url === '/usuarios') {
res.end('<h1>Lista de usuarios</h1>')
} else {
res.end('<h1>404 Not Found</h1>')
}
})
Manejo correcto de códigos de estado
Un error muy común es olvidar indicar el código de estado adecuado. Por defecto, Node.js envía un 200 OK, incluso si el contenido que estás enviando es un mensaje de error.
Los status codes HTTP deben indicarse explícitamente usando la propiedad res.statusCode.
if (url === '/') {
res.statusCode = 200 // Éxito
res.end('Home')
} else {
res.statusCode = 404 // No encontrado
res.end('No encontrado')
}
Tip: Al establecer correctamente el código de estado, el navegador, las herramientas de desarrollo y los clientes de API (como Postman o Insomnia) pueden interpretar correctamente qué ha sucedido con la petición.
Importancia del return en las respuestas
Un detalle fundamental al programar servidores es detener la ejecución tras enviar una respuesta. Si no usas return después de un res.end(), el código que haya debajo se seguirá ejecutando.
Si Node.js intenta escribir más datos en una respuesta que ya ha terminado, lanzará el error: ERR_HTTP_HEADERS_SENT.
if (url === '/') {
res.end('Home')
return // 👈 ¡Fundamental para terminar aquí la ejecución!
}
El problema del Content-Type
Aunque estés devolviendo un objeto convertido a texto, eso no lo convierte automáticamente en un JSON para el cliente.
Si no indicamos el header correcto:
- El navegador lo interpreta como texto plano (
text/plain). - Las herramientas no formatean el contenido.
- El cliente no sabe que debe parsear la respuesta como un objeto.
Para JSON, el header obligatorio debe ser:
Content-Type: application/json
Devolver JSON correctamente
Para devolver JSON de forma profesional, debemos hacer dos cosas:
- Establecer el header
Content-Type. - Convertir el objeto de JavaScript a una cadena de texto con
JSON.stringify.
const user = { name: 'midudev', role: 'admin' }
res.setHeader('Content-Type', 'application/json; charset=utf-8')
res.end(JSON.stringify(user))
Unificar la forma de responder
Escribir siempre los mismos headers y conversiones se vuelve repetitivo muy rápido. Una buena práctica es crear una función auxiliar que simplifique este proceso:
const sendResponse = (res, statusCode, data) => {
res.statusCode = statusCode
res.setHeader('Content-Type', 'application/json; charset=utf-8')
res.end(JSON.stringify(data))
}
// Uso mucho más limpio:
if (url === '/api/user') {
return sendResponse(res, 200, { name: 'midu' })
}
Respuestas de error en formato JSON
Incluso los errores deberían devolverse como JSON. En lugar de enviar texto plano para un 404, es mucho mejor devolver un objeto estructurado:
return sendResponse(res, 404, {
error: 'Not Found',
message: 'La ruta solicitada no existe en este servidor',
})
Esto hace que la API sea mucho más predecible y fácil de consumir por otros desarrolladores.
Por qué esto es importante
Todo lo que hemos visto en esta clase es:
- Exactamente lo que hacen frameworks como Express por debajo (el famoso
res.json()). - La base para entender cómo se comunican las aplicaciones modernas.
- La forma de evitar tratar a las librerías como “magia negra”.
Lo que hemos visto
- ✅ Discriminar rutas manualmente usando
req.url. - ✅ Manejar correctamente los códigos de estado HTTP.
- ✅ Usar el header
Content-Typepara respuestas JSON. - ✅ Unificar y simplificar el envío de respuestas.
- ✅ Devolver errores de forma consistente.
Con esto ya tienes un servidor mucho más realista. En la siguiente clase empezaremos a ver por qué herramientas como Express existen para hacernos la vida más fácil.