🚦 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
- ¿Qué es HTTP? - Conceptos básicos de HTTP
- Métodos HTTP - GET, POST, PUT, DELETE
- Encabezados HTTP - Encabezados de solicitud/respuesta
- ¿Qué es una API? - Conceptos básicos de API
🎬 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.