Express.js
404, recurso inexistente y 405
Diferencia ruta inexistente, recurso no encontrado y método no permitido, y explica cómo responder 404 y 405 de forma coherente en Express.js.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
Express.js
Diferencia ruta inexistente, recurso no encontrado y método no permitido, y explica cómo responder 404 y 405 de forma coherente en Express.js.
Una ruta inexistente, un recurso inexistente y un método no permitido pueden compartir parte de la URL, pero representan problemas distintos del contrato.
Debes distinguir:
ninguna ruta coincide
→ 404 ROUTE_NOT_FOUND
la ruta coincide, pero no existe un recurso visible
→ 404 ORDER_NOT_FOUND
el path pertenece a un contrato, pero el método no está permitido
→ 405 METHOD_NOT_ALLOWED + AllowEl status puede ser igual en los dos primeros casos, pero el diagnóstico y el código público no lo son.
Se implementa como middleware terminal después de todos los routers:
app.use((request, response) => {
response.status(404).json({
code: 'ROUTE_NOT_FOUND',
method: request.method,
path: request.path,
requestId: response.locals.requestId,
});
});No incluyas query sensible ni detalles internos. Este middleware solo corre si ninguna capa anterior respondió o propagó un error.
La ruta sí existe:
GET /orders/550e8400-e29b-41d4-a716-446655440000El caso de uso puede no encontrar una orden visible. Esto se expresa con un error de aplicación:
if (!order) {
throw new OrderNotFoundError(orderId);
}El error middleware lo convierte en ORDER_NOT_FOUND.
Si el recurso existe pero pertenece a otro tenant, responder 404 puede evitar enumeración. Otra API puede usar 403. La política depende de si revelar existencia es aceptable.
La consulta puede incorporar el scope:
SELECT *
FROM orders
WHERE id = $1
AND business_id = $2;Así, inexistencia y falta de visibilidad producen el mismo resultado sin cargar datos ajenos.
Un 405 significa que el servidor reconoce el recurso o path, pero no acepta ese método:
DELETE /orders
Allow: GET, POSTExpress no genera automáticamente una matriz 405 para todos los routers. Opciones:
No inventes una solución compleja si la API no necesita distinguirlos, pero comprende la diferencia.
Un endpoint puede responder capacidades o preflight CORS. No uses el resultado como autorización; que un método aparezca en Allow no significa que cualquier actor pueda ejecutarlo.
El 404 terminal también funciona como red de seguridad: cualquier request que atraviese todo el pipeline obtiene una respuesta. Si falta, Express puede usar su handler predeterminado, que quizá responda HTML en una API JSON.
app.use('/api/orders', ordersRouter);
app.use(routeNotFound);
app.use(errorHandler);Si el 404 aparece antes del router, intercepta todas las requests. Si aparece después del error handler, los errores no siguen la secuencia esperada.
const routeNotFound: RequestHandler = (request, response) => {
response.status(404).json({
type: 'https://api.example.com/problems/route-not-found',
title: 'La ruta solicitada no existe',
status: 404,
code: 'ROUTE_NOT_FOUND',
requestId: response.locals.requestId,
});
};Un OrderNotFoundError utiliza el mismo envelope con otro type y code.
/orders/not-a-uuid coincide con la ruta, pero falla validación. No es route 404; normalmente es 400/422 según política.
Puede existir al inicio y desaparecer antes de update. Verifica filas afectadas y traduce el resultado.
La configuración de routing define si coincide. Añade tests para canonicalización.
Un servidor que también entrega frontend puede responder index.html a rutas del navegador. No debe capturar rutas API desconocidas.
Un recurso temporalmente ausente puede aparecer después. Define cache headers adecuados.
Allow.Incluye:
OPTIONSDistinguir 404 y 405 mejora precisión y tooling, pero requiere metadata adicional. Ocultar permisos con 404 reduce enumeración, pero puede dificultar diagnóstico del usuario autorizado. Documenta la política.
/orders/not-a-uuid no es necesariamente route 404?Allow, con los métodos aceptados.Asincronía en handlers profundiza cómo Promises, callbacks y trabajo desprendido interactúan con el lifecycle.