====== 03 - El protocolo HTTP ======
La **web** funciona sobre **HTTP** (*HyperText Transfer Protocol*), un **protocolo de aplicación** cliente-servidor sobre **TCP**: el cliente envía una **petición** con formato definido y el servidor responde con una **respuesta** con otro formato igualmente definido. Todo servidor web de este módulo se dedica, en el fondo, a leer peticiones y escribir respuestas con ese formato.
* **Cliente-servidor:** el cliente toma siempre la iniciativa; el servidor escucha y responde.
* **Sin estado:** cada petición es independiente; el servidor no recuerda nada entre peticiones.
* **Texto legible** en **HTTP/1.1**: petición y respuesta pueden leerse y escribirse a mano, lo que permite construirlas desde un servidor de sockets.
===== 1. Petición =====
GET /books/42 HTTP/1.1
Host: localhost:8080
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
* **Línea de petición:** método, ruta y versión.
* **Cabeceras:** pares ''Nombre: valor'' (una por línea) con información sobre la petición.
* **Línea en blanco:** separa cabeceras y cuerpo (aquí el cuerpo está vacío, como en todo ''GET'').
* **Cuerpo:** los datos que el cliente envía; el formato lo anuncia ''Content-Type''.
Un ''POST'' que crea un libro incluye cuerpo:
POST /books HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 47
{"title":"Código limpio","author":"R. Martin"}
===== 2. Métodos =====
El **método** expresa la intención del cliente sobre el recurso que identifica la ruta:
^ Método ^ Intención ^
| ''GET'' | Leer el recurso; no modifica nada |
| ''POST'' | Crear un recurso (o ejecutar una operación) |
| ''PUT'' | Reemplazar un recurso existente |
| ''DELETE'' | Eliminar un recurso |
===== 3. Cabeceras =====
^ Cabecera ^ Qué indica ^
| ''Host'' | Servidor y puerto solicitados (obligatoria en HTTP/1.1) |
| ''Accept'' | Formatos que el cliente entiende |
| ''Content-Type'' | Formato del cuerpo (en petición y respuesta) |
| ''Content-Length'' | Tamaño del cuerpo en bytes |
| ''Authorization'' | Credenciales: con **tokens**, ''Bearer '' |
===== 4. Respuesta =====
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 33
{"id":42,"title":"Código limpio"}
* **Línea de estado:** versión, **código de estado** y frase explicativa.
* **Cabeceras:** ''Content-Type'', ''Content-Length''...
* **Cuerpo:** los datos, en el formato que anuncia ''Content-Type''.
El código de estado resume el resultado; su primera cifra indica la familia:
^ Código ^ Significado ^
| ''200'' | OK: petición atendida |
| ''201'' | Recurso creado |
| ''204'' | Éxito sin cuerpo |
| ''301'' | Redirección permanente |
| ''400'' | Petición mal formada |
| ''401'' | No autenticado: falta el token o no es válido |
| ''403'' | Autenticado, pero sin permiso |
| ''404'' | No encontrado |
| ''405'' | Método no admitido en esa ruta |
| ''500'' | Error interno del servidor |
Familias: **2xx** éxito, **3xx** redirección, **4xx** error del cliente, **5xx** error del servidor. La elección del código forma parte del contrato de la API.
===== 5. Observar el protocolo con curl =====
''curl'' envía la petición y muestra la respuesta; con ''-v'' (*verbose*) muestra ambas tal cual cruzan la red:
$ curl -v http://localhost:8080/books/42
> GET /books/42 HTTP/1.1
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 33
<
{"id":42,"title":"Código limpio"}
* Las líneas con ''>'' son lo que envía el cliente (la petición).
* Las líneas con ''<'' son lo que responde el servidor (la respuesta).
===== 6. Intercambio =====
@startuml
actor "Cliente" as C
participant "Servidor HTTP" as S
C -> S : GET /books/42
S --> C : 200 OK (JSON)
C -> S : POST /books (JSON)
S --> C : 201 Created
@enduml
**HTTP no tiene estado**: el servidor no recuerda al cliente entre peticiones. La autenticación con **tokens** se apoya en esto: cada petición trae su token en la cabecera ''Authorization''. No se usan sesiones ni cookies.