📬 Métodos HTTP
📖 Definición
Métodos HTTP representan la acción que un cliente quiere que el servidor realice. Cada método tiene un significado y propósito específico, siendo fundamental para el diseño de APIs RESTful.
🎯 Comprendiendo con analogías
Sistema de biblioteca
GET = Buscar un libro (consulta)
├─ Preguntar al bibliotecario "¿Tienen este libro?"
├─ Solo recupera datos
└─ Sin cambiar el estado de la biblioteca
POST = Registrar un nuevo libro (creación)
├─ Añadir un libro nuevo a la biblioteca
├─ Cambia el estado de la biblioteca
└─ Crea un nuevo recurso
PUT = Actualizar toda la información del libro (actualización total)
├─ Reescribir toda la información del libro
└─ Reemplaza completamente
PATCH = Actualizar parte de la información del libro (actualización parcial)
├─ Modificar solo parte de la información (ej. disponibilidad)
└─ Cambiar solo una parte
DELETE = Dar de baja un libro (eliminación)
├─ Eliminar el libro de la biblioteca
└─ Eliminar un recurso
💡 Métodos HTTP principales
GET - Consultar datos
Propósito: Recuperar recursos del servidor
Características:
├─ Seguro (Safe): No modifica el estado del servidor
├─ Idempotente: Múltiples llamadas devuelven el mismo resultado
├─ Puede ser cacheado
└─ Permanece en el historial del navegador
Ejemplo de solicitud:
GET /api/users HTTP/1.1
Host: example.com
// API Fetch de JavaScript
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => console.log(data));
// jQuery
$.get('https://api.example.com/users', function(data) {
console.log(data);
});
// axios
axios.get('https://api.example.com/users')
.then(response => console.log(response.data));
# curl
curl https://api.example.com/users
# Consultar usuario específico
curl https://api.example.com/users/123
# Usar parámetros de consulta
curl "https://api.example.com/users?page=1&limit=10"
Ejemplo de respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
{
"users": [
{ "id": 1, "name": "María González" },
{ "id": 2, "name": "Carlos Sánchez" }
]
}
POST - Crear datos
Propósito: Crear un nuevo recurso en el servidor
Características:
├─ No es seguro: Cambia el estado del servidor
├─ No es idempotente: Varias llamadas crean múltiples recursos
├─ No puede ser cacheado
└─ Incluye datos en el cuerpo de la solicitud
Ejemplo de solicitud:
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "María González",
"email": "maria@example.com"
}
// API Fetch
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'María González',
email: 'maria@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));
// axios
axios.post('https://api.example.com/users', {
name: 'María González',
email: 'maria@example.com'
})
.then(response => console.log(response.data));
# curl
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"María González","email":"maria@example.com"}'
Ejemplo de respuesta:
HTTP/1.1 201 Created
Location: /api/users/123
Content-Type: application/json
{
"id": 123,
"name": "María González",
"email": "maria@example.com",
"createdAt": "2025-01-26T10:00:00Z"
}
PUT - Actualización total de datos
Propósito: Reemplazar completamente un recurso con nuevos datos
Características:
├─ No es seguro: Cambia el estado del servidor
├─ Idempotente: Múltiples llamadas producen el mismo resultado
├─ Reemplaza todo el recurso
└─ Puede crear el recurso si no existe
Ejemplo de solicitud:
PUT /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "María González",
"email": "nuevo-email@example.com",
"phone": "666123456"
}
// API Fetch
fetch('https://api.example.com/users/123', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'María González',
email: 'nuevo-email@example.com',
phone: '666123456'
})
})
.then(response => response.json())
.then(data => console.log(data));
// axios
axios.put('https://api.example.com/users/123', {
name: 'María González',
email: 'nuevo-email@example.com',
phone: '666123456'
})
.then(response => console.log(response.data));
# curl
curl -X PUT https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"name":"María González","email":"nuevo-email@example.com","phone":"666123456"}'
PATCH - Actualización parcial de datos
Propósito: Modificar solo una parte del recurso
Características:
├─ No es seguro: Cambia el estado del servidor
├─ Puede ser o no idempotente
├─ Modifica solo algunos campos
└─ Más eficiente que PUT
Ejemplo de solicitud:
PATCH /api/users/123 HTTP/1.1
Host: example.com
Content-Type: application/json
{
"email": "nuevo-email@example.com"
}
// API Fetch
fetch('https://api.example.com/users/123', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'nuevo-email@example.com'
})
})
.then(response => response.json())
.then(data => console.log(data));
// axios
axios.patch('https://api.example.com/users/123', {
email: 'nuevo-email@example.com'
})
.then(response => console.log(response.data));
# curl
curl -X PATCH https://api.example.com/users/123 \
-H "Content-Type: application/json" \
-d '{"email":"nuevo-email@example.com"}'
Comparación PUT vs PATCH:
Datos originales:
{
"id": 123,
"name": "María González",
"email": "antiguo@example.com",
"phone": "666111222"
}
Solicitud PUT (reemplaza completamente):
{
"name": "María González",
"email": "nuevo@example.com"
}
Resultado:
{
"id": 123,
"name": "María González",
"email": "nuevo@example.com"
// ¡Campo de teléfono desaparece!
}
Solicitud PATCH (modificación parcial):
{
"email": "nuevo@example.com"
}
Resultado:
{
"id": 123,
"name": "María González",
"email": "nuevo@example.com",
"phone": "666111222"
// ¡Campo de teléfono se mantiene!
}
DELETE - Eliminar datos
Propósito: Eliminar un recurso
Características:
├─ No es seguro: Cambia el estado del servidor
├─ Idempotente: Múltiples llamadas producen el mismo resultado
├─ El cuerpo de respuesta puede estar vacío
└─ Potencialmente irreversible
Ejemplo de solicitud:
DELETE /api/users/123 HTTP/1.1
Host: example.com
// API Fetch
fetch('https://api.example.com/users/123', {
method: 'DELETE'
})
.then(response => {
if (response.ok) {
console.log('Eliminación completada');
}
});
// axios
axios.delete('https://api.example.com/users/123')
.then(response => console.log('Eliminación completada'));
# curl
curl -X DELETE https://api.example.com/users/123
Ejemplo de respuesta:
HTTP/1.1 204 No Content
O
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "Usuario eliminado",
"deletedId": 123
}
🔍 Otros métodos HTTP
HEAD - Solo consultar encabezados
Propósito: Igual que GET, pero solo devuelve encabezados sin cuerpo
Casos de uso:
├─ Verificar existencia de recurso
├─ Comprobar tamaño de archivo
└─ Verificar tiempo de modificación
Ejemplo:
HEAD /api/users/123 HTTP/1.1
Host: example.com
Respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 256
Last-Modified: Sat, 26 Jan 2025 10:00:00 GMT
# curl
curl -I https://api.example.com/users/123
OPTIONS - Verificar métodos soportados
Propósito: Verificar métodos soportados por el servidor (usado en preflight de CORS)
Ejemplo:
OPTIONS /api/users HTTP/1.1
Host: example.com
Respuesta:
HTTP/1.1 200 OK
Allow: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Origin: *
# curl
curl -X OPTIONS https://api.example.com/users -i
📊 Comparación de atributos de métodos
┌─────────┬──────┬────────┬─────────┬────────────┐
│ Método │ Seguro│ Idempot│ Cacheable│ Cuerpo req│
├─────────┼──────┼────────┼─────────┼────────────┤
│ GET │ ✅ │ ✅ │ ✅ │ ❌ │
│ POST │ ❌ │ ❌ │ ❌ │ ✅ │
│ PUT │ ❌ │ ✅ │ ❌ │ ✅ │
│ PATCH │ ❌ │ △ │ ❌ │ ✅ │
│ DELETE │ ❌ │ ✅ │ ❌ │ △ │
│ HEAD │ ✅ │ ✅ │ ✅ │ ❌ │
│ OPTIONS │ ✅ │ ✅ │ ❌ │ ❌ │
└─────────┴──────┴────────┴─────────┴────────────┘
Explicación de términos:
- Seguro (Safe): No modifica estado del servidor
- Idempotente: Múltiples ejecuciones producen mismo resultado
- Cacheable: Respuesta puede ser cacheada
💡 Diseño de API RESTful
Mapeo CRUD con métodos HTTP
Create → POST
Read → GET
Update → PUT / PATCH
Delete → DELETE
Ejemplo de API RESTful
Recurso: Usuarios (users)
GET /users - Listar usuarios
GET /users/123 - Consultar usuario
POST /users - Crear usuario
PUT /users/123 - Modificar usuario completamente
PATCH /users/123 - Modificar usuario parcialmente
DELETE /users/123 - Eliminar usuario
Recursos anidados:
GET /users/123/posts - Listar publicaciones de usuario
GET /users/123/posts/456 - Consultar publicación
POST /users/123/posts - Crear publicación
PUT /users/123/posts/456 - Modificar publicación
DELETE /users/123/posts/456 - Eliminar publicación
Ejemplo práctico: API de blog
// API de publicaciones de blog
// 1. Listar publicaciones (paginación, filtrado)
GET /api/posts?page=1&limit=10&category=tech
// 2. Consultar publicación específica
GET /api/posts/123
// 3. Crear publicación
POST /api/posts
{
"title": "Dominando métodos HTTP",
"content": "...",
"category": "tech"
}
// 4. Modificar publicación completamente
PUT /api/posts/123
{
"title": "Dominando métodos HTTP (actualizado)",
"content": "...",
"category": "tech"
}
// 5. Modificar parcialmente (incrementar visualizaciones)
PATCH /api/posts/123
{
"views": 101
}
// 6. Eliminar publicación
DELETE /api/posts/123
// 7. Relacionados con comentarios
GET /api/posts/123/comments - Listar comentarios
POST /api/posts/123/comments - Crear comentario
DELETE /api/posts/123/comments/456 - Eliminar comentario
🤔 Preguntas frecuentes
Q1. ¿Cuál es la diferencia entre POST y PUT?
R:
POST:
├─ Crear nuevo recurso
├─ Servidor decide URI del recurso
├─ No idempotente (varias llamadas crean varios recursos)
└─ Ejemplo: POST /users
PUT:
├─ Reemplazar recurso completamente
├─ Cliente especifica URI del recurso
├─ Idempotente (múltiples llamadas mismo resultado)
└─ Ejemplo: PUT /users/123
Analogía práctica:
POST = "Por favor, cree una nueva cuenta" (banco asigna número)
PUT = "Reemplace completamente la información de la cuenta 123"
Q2. ¿Puedo enviar un cuerpo en una solicitud GET?
R:
Técnicamente posible, pero:
├─ Permitido en especificación HTTP, no recomendado
├─ Muchos servidores/frameworks lo ignoran
├─ Problemas en caché y registro
└─ Se recomienda usar parámetros de consulta
❌ Ejemplo incorrecto:
GET /api/users
{
"filters": { "age": 25 }
}
✅ Ejemplo correcto:
GET /api/users?age=25
O para búsquedas complejas, usar POST:
POST /api/users/search
{
"filters": { "age": 25, "city": "Madrid" }
}
Q3. ¿Puedo enviar un cuerpo en una solicitud DELETE?
R:
Posible, pero con precaución:
├─ Permitido en especificación HTTP
├─ Algunos servidores/proxies pueden ignorarlo
├─ Normalmente ID de recurso en URI
└─ Cuerpo para información adicional
Ejemplos de uso:
✅ Método tradicional:
DELETE /api/users/123
✅ Eliminación por lotes:
DELETE /api/posts/bulk
{
"ids": [1, 2, 3, 4, 5]
}
✅ Enviar razón de eliminación:
DELETE /api/users/123
{
"reason": "Solicitud de usuario",
"confirm": true
}
Q4. ¿Por qué es importante la idempotencia?
R:
Importancia de la idempotencia:
1. Respuesta a fallos de red
├─ Posibilidad de reintentar solicitudes
├─ Sin preocupación por solicitudes duplicadas
└─ Reprocesamiento seguro
Ejemplos:
GET /users/123 → Seguro consultar varias veces
POST /users → ¡Varias llamadas crean múltiples usuarios!
PUT /users/123 → Múltiples llamadas mismo resultado
DELETE /users/123 → Múltiples eliminaciones mismo resultado
2. Lógica de reintento de cliente
├─ Reintentar de forma segura en caso de timeout
└─ Implementar mecanismos de reintento automático
3. Caché y optimización
├─ Solicitudes idempotentes pueden ser cacheadas
└─ Optimización de rendimiento
Q5. ¿Cuáles son los criterios para elegir método en la práctica?
R:
Guía de selección:
1. Solo consulta de datos
→ GET
2. Crear nuevo dato
→ POST
3. Reemplazar completamente datos
→ PUT
Ejemplo: Actualización completa de perfil
4. Modificar parte de los datos
→ PATCH
Ejemplo: Incrementar número de likes, cambiar estado
5. Eliminar datos
→ DELETE
6. Consulta/búsqueda compleja
→ POST /search
(Evitar límites de longitud de URL de GET)
Ejemplo práctico:
// ✅ Buen ejemplo
GET /api/products - Listar productos
GET /api/products/123 - Detalles de producto
POST /api/products - Registrar producto
PATCH /api/products/123/stock - Modificar solo stock
PUT /api/products/123 - Modificar información completa
DELETE /api/products/123 - Eliminar producto
// ❌ Mal ejemplo
GET /api/deleteProduct?id=123 - Eliminar con GET
POST /api/getProducts - Consultar con POST
POST /api/updateProduct - Modificar con POST
🎓 Prácticas
1. Práctica con API Fetch
// Solicitud GET
async function getUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
const data = await response.json();
return data;
}
// Solicitud POST
async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
return await response.json();
}
// Solicitud PUT
async function updateUser(id, userData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
return await response.json();
}
// Solicitud PATCH
async function patchUser(id, partialData) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(partialData)
});
return await response.json();
}
// Solicitud DELETE
async function deleteUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`, {
method: 'DELETE'
});
return response.ok;
}
2. Manejo de errores
async function apiRequest(url, options = {}) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`Error HTTP! estado: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Solicitud API fallida:', error);
throw error;
}
}
// Ejemplo de uso
try {
const user = await apiRequest('https://api.example.com/users/123');
console.log(user);
} catch (error) {
console.error('Consulta de usuario fallida');
}
🔗 Documentos relacionados
- ¿Qué es HTTP? - Conceptos básicos de HTTP
- Códigos de estado HTTP - Significado de 200, 404, 500
- Encabezados HTTP - Encabezados de solicitud/respuesta
- ¿Qué es una API? - Conceptos básicos de API
🎬 Conclusión
¡Los métodos HTTP son fundamentales para las API RESTful! Comprender las características de cada método te permitirá diseñar APIs intuitivas y fáciles de mantener.
Siguiente paso: Lee Códigos de estado HTTP para entender 200, 404, 500 y otros códigos.