====== 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.