Saltar al contenido principal

🚦 Códigos de estado HTTP

[... previous content remains the same ...]

❌ 4xx - Errores de cliente

400 Bad Request

Formato de solicitud incorrecto

Solicitud:
POST /api/users HTTP/1.1
Content-Type: application/json

{
"name": "", // Nombre vacío
"email": "email-invalido" // Formato de correo incorrecto
}

Respuesta:
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": "Error de validación",
"message": "Datos de solicitud no válidos",
"details": [
{
"field": "name",
"message": "El nombre es requerido"
},
{
"field": "email",
"message": "Formato de correo inválido"
}
]
}
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: '',
email: 'email-invalido'
})
})
.then(response => {
if (response.status === 400) {
return response.json();
}
})
.then(error => {
console.error('Validación fallida:', error);
});

401 Unauthorized

Autenticación necesaria

Solicitud:
GET /api/perfil HTTP/1.1

Respuesta:
HTTP/1.1 401 No autorizado
WWW-Authenticate: Bearer realm="ejemplo"
Content-Type: application/json

{
"error": "No autorizado",
"message": "Autenticación requerida"
}
fetch('https://api.example.com/perfil', {
headers: {
'Authorization': 'Bearer TU_TOKEN'
}
})
.then(response => {
if (response.status === 401) {
console.error('Autenticación necesaria - Redirigir a login');
window.location.href = '/login';
}
});

Casos de uso:

  • Usuario no autenticado
  • Token expirado
  • Credenciales de autenticación incorrectas

403 Forbidden

Sin permisos

Solicitud:
DELETE /api/users/999 HTTP/1.1
Authorization: Bearer token_usuario

Respuesta:
HTTP/1.1 403 Prohibido
Content-Type: application/json

{
"error": "Prohibido",
"message": "No tienes permiso para eliminar este usuario"
}
fetch('https://api.example.com/admin/users/999', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer TOKEN_USUARIO'
}
})
.then(response => {
if (response.status === 403) {
console.error('Sin permisos');
alert('Solo los administradores pueden eliminar');
}
});

401 vs 403:

401 No autorizado (fallo de autenticación)
├─ "No sé quién eres"
├─ No ha iniciado sesión
├─ Sin token o token expirado
└─ Solución: Iniciar sesión

403 Prohibido (fallo de autorización)
├─ "Sé quién eres, pero no tienes permisos"
├─ Sesión iniciada
├─ Permisos insuficientes
└─ Solución: Solicitar permisos al administrador

404 Not Found

Recurso no encontrado

Solicitud:
GET /api/users/999999 HTTP/1.1

Respuesta:
HTTP/1.1 404 No encontrado
Content-Type: application/json

{
"error": "No encontrado",
"message": "Usuario con ID 999999 no encontrado"
}
fetch('https://api.example.com/users/999999')
.then(response => {
if (response.status === 404) {
console.error('Usuario no encontrado');
// Mostrar página 404
}
return response.json();
});

Casos de uso:

  • Página inexistente
  • Recurso eliminado
  • URL incorrecta

Otros códigos 4xx

405 Método no permitido
├─ Método HTTP no permitido
└─ Ejemplo: POST en un endpoint que solo acepta GET

409 Conflicto
├─ Solicitud en conflicto con el estado actual del servidor
└─ Ejemplo: Intentar registrar un email ya existente

422 Entidad no procesable
├─ Sintaxis correcta pero semánticamente no procesable
└─ Ejemplo: Fecha correcta pero en futuro

429 Demasiadas solicitudes
├─ Límite de solicitudes excedido
└─ Ejemplo: Límite de llamadas a API

Manejo de 429 Demasiadas solicitudes

async function fetchWithRetry(url, options = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Demasiadas solicitudes. Reintentando en ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}

return response;
}

throw new Error('Máximo de reintentos excedido');
}

🔥 5xx - Errores de servidor

500 Error interno del servidor

Error interno del servidor

Solicitud:
GET /api/users HTTP/1.1

Respuesta:
HTTP/1.1 500 Error interno del servidor
Content-Type: application/json

{
"error": "Error interno del servidor",
"message": "Ocurrió un error inesperado"
}
fetch('https://api.example.com/users')
.then(response => {
if (response.status === 500) {
console.error('Error del servidor');
alert('Error temporal. Inténtelo de nuevo más tarde.');
}
});

Causas:

  • Errores de código
  • Excepciones no manejadas
  • Errores de base de datos
  • Problemas de configuración de servidor

502 Bad Gateway

Error de gateway

Respuesta:
HTTP/1.1 502 Bad Gateway
Content-Type: text/html

<html>
<body>
<h1>502 Bad Gateway</h1>
<p>El servidor recibió una respuesta inválida del servidor upstream</p>
</body>
</html>

Causas:

  • Fallo de comunicación entre servidores proxy y backend
  • Servidor backend caído
  • Problemas de red

503 Servicio no disponible

Servicio no disponible

Respuesta:
HTTP/1.1 503 Servicio no disponible
Retry-After: 3600
Content-Type: application/json

{
"error": "Servicio no disponible",
"message": "Servidor en mantenimiento",
"retryAfter": 3600
}
fetch('https://api.example.com/users')
.then(response => {
if (response.status === 503) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Servicio en mantenimiento. Reintentar en ${retryAfter} segundos`);
}
});

Causas:

  • Mantenimiento de servidor
  • Sobrecarga
  • Interrupción temporal

504 Gateway Timeout

Timeout de gateway

Respuesta:
HTTP/1.1 504 Gateway Timeout
Content-Type: application/json

{
"error": "Gateway Timeout",
"message": "El servidor no respondió a tiempo"
}

Causas:

  • Respuesta lenta del servidor backend
  • Latencia de red
  • Timeout de consulta a base de datos

[... rest of the document remains consistent with previous sections]

🎓 Prácticas

Manejo de todos los códigos de estado

async function handleResponse(response) {
// 2xx
if (response.ok) {
if (response.status === 204) {
return null; // Sin contenido
}
return await response.json();
}

// 3xx
if (response.status >= 300 && response.status < 400) {
const location = response.headers.get('Location');
console.log('Redireccionando:', location);
return null;
}

// 4xx
if (response.status >= 400 && response.status < 500) {
const error = await response.json();
throw new Error(error.message || 'Error de cliente');
}

// 5xx
if (response.status >= 500) {
throw new Error('Error de servidor');
}
}

Probar códigos de estado

// Usar httpstat.us para pruebas
async function testStatusCodes() {
const codes = [200, 201, 204, 400, 401, 403, 404, 500, 503];

for (const code of codes) {
try {
const response = await fetch(`https://httpstat.us/${code}`);
console.log(`${code}: ${response.statusText}`);
} catch (error) {
console.error(`${code}: Error`, error);
}
}
}

🔗 Documentos relacionados

🎬 Conclusión

¡Los códigos de estado HTTP son fundamentales para la comunicación clara entre clientes y servidores! Utilizarlos correctamente mejora la depuración, facilita el manejo de errores y permite crear APIs más robustas.

Siguiente paso: Lea Encabezados HTTP para entender Content-Type, Authorization y otros encabezados.