En este documento, se explica cómo funcionan las APIs de Google con diversas versiones e implementaciones de HTTP. Si usas nuestras bibliotecas cliente generadas o hechas de forma manual (el enfoque recomendado para la mayoría de los casos prácticos), no debes preocuparte por estos detalles. Las bibliotecas controlan automáticamente la comunicación de bajo nivel con el servidor.
Si eres un desarrollador experimentado que escribe código personalizado para acceder a la interfaz REST de una API con un cliente HTTP de terceros, debes comprender los conceptos relevantes que se documentan aquí, junto con las funciones que proporciona la biblioteca HTTP que elijas.
Trabaja con protocolos de conexión estándar (HTTP/*)
En esta sección, se describen los protocolos de conexión estándar compatibles (por lo general, una versión de HTTP) que las APIs de Google pueden usar para la comunicación entre clientes y servidores, y cómo recomendamos que los uses.
Semántica de HTTP
Cuando desarrolles código de cliente de API, sigue la semántica de protocolo HTTP estándar. Es posible que los proxies del servidor o las pilas de API solo admitan un subconjunto de las funciones HTTP estándar y que también admitan sus versiones compatibles con versiones anteriores.
La pila del servidor controla la semántica del protocolo HTTP que necesita la administración mediante implementaciones de API del lado del servidor. Solo confíe en dicha semántica si estas características están documentadas de forma explícita como parte de las especificaciones de la API, como la asistencia de almacenamiento en caché.
Versiones de HTTP
Los clientes pueden usar cualquier protocolo HTTP/*, como se permite en la plataforma del cliente o en la red del lado del cliente, o como se negocia con el proxy del lado del servidor. Los protocolos admitidos incluyen HTTP/1.1, HTTP/2 y HTTP/3 (QUIC). Se desaconseja el uso de la compatibilidad heredada con HTTP/1.0.
Es posible que algunas funciones de la API solo sean compatibles con versiones más recientes de los protocolos HTTP; algunas solo se especifican por completo con HTTP/2 y HTTP/3, como la transmisión multiplexada dúplex completo. Ten en cuenta las limitaciones de las diferentes versiones de HTTP si necesitas cualquiera de estas características como parte de las especificaciones de la API. Ten en cuenta que las funciones más antiguas, como la extracción del servidor HTTP/2, están obsoletas y no son compatibles con los clientes web modernos.
Por lo general, recomendamos HTTP/3 o HTTP/2 para obtener un mejor rendimiento, reducir el bloqueo de cabeza de línea y aumentar la resiliencia a las fallas de red.
Canales
Los canales hacen referencia a las conexiones de red de capa 4, que suelen ser sockets TCP para HTTP/1.1 y HTTP/2, y sockets UDP para HTTP/3 (QUIC). Las aplicaciones cliente no deberían hacer suposiciones sobre cómo se administran los canales de extremo a extremo, ya que los proxies de Google Front End (GFE) casi siempre finalizan las conexiones en nombre del proceso del servidor.
Clientes de HTTP/1.1: Si usas HTTP/1.1, siempre vuelve a usar las conexiones TCP (Connection: Keep-Alive). Las bibliotecas cliente de HTTP suelen administrar un grupo de conexiones para facilitar la reutilización. Evita el encauzamiento HTTP en las conexiones HTTP/1.1, ya que no se admite bien y puede generar problemas. Para obtener más información, consulta HTTP y TCP.
Clientes de HTTP/2 y HTTP/3: Los clientes y navegadores modernos usan principalmente HTTP/2 o HTTP/3. Ambos protocolos admiten la multiplexación, lo que permite que varias solicitudes y respuestas estén en tránsito de forma simultánea a través de una sola conexión.
- HTTP/2: Usa una sola conexión TCP por origen.
- HTTP/3: Usa una sola conexión QUIC a través de UDP por origen. QUIC integra el cifrado TLS, el control de congestión y la administración de conexiones, y suele proporcionar beneficios como una configuración de conexión más rápida (0-RTT o 1-RTT) y resistencia al bloqueo de línea de TCP en las transmisiones.
Con HTTP/2 y HTTP/3, los límites del navegador en la cantidad de conexiones TCP paralelas a un solo host (por ejemplo, de 2 a 10) ya no son una preocupación principal para el rendimiento. Sin embargo, ten en cuenta que los servidores (o los proxies como GFE) aún pueden aplicar límites en la cantidad máxima de transmisiones simultáneas dentro de una sola conexión HTTP/2 o HTTP/3. Esto evita la sobrecarga y garantiza un uso justo de los recursos (por ejemplo, limitando las solicitudes o transmisiones simultáneas por conexión a 100).
HTTPS
Los clientes pueden acceder a una API a través de HTTPS o HTTP, como lo admite la especificación de la API. La negociación de TLS y las versiones de TLS son transparentes para las aplicaciones cliente. De manera predeterminada, las API de Google solo aceptan tráfico HTTPS.
Formatos de solicitudes y respuestas
En esta sección, se describe la estructura de las interacciones con la API, incluido el uso de datos codificados como URL, métodos HTTP específicos para acciones de RESTful y formatos de cargas útiles basados en JSON.
URL de solicitud
La asignación JSON-REST admite datos de solicitudes con codificación URL, y el cuerpo de la respuesta y solicitud HTTP usan application/json como Content-Type.
El cuerpo HTTP usa un arreglo JSON para admitir métodos RPC transmitidos. El arreglo JSON puede contener cualquier cantidad de mensajes JSON o un mensaje JSON de estado de error.
URLs de solicitudes largas
La URL tiene una limitación de longitud práctica, que suele establecerse en 16 KB de forma predeterminada, aunque esto puede variar según el servidor. Si tu API usa solicitudes GET con URLs que exceden esta longitud, es posible que las solicitudes no lleguen al servidor de la API de destino y que el Google Front End (GFE) las rechace con el mensaje de error Your client has issued a malformed or illegal request..
Para omitir la limitación, el código de cliente debe usar una solicitud POST con un Content-Type de application/x-www-form-urlencoded junto con el encabezado HTTP X-HTTP-Method-Override: GET. Este enfoque también funciona para las solicitudes DELETE.
Métodos HTTP (verbos)
Si las solicitudes URL siguen el modelo REST, sus métodos HTTP se especifican como parte de la especificación de la API. En particular, cada método de la API debe cumplir con los requisitos del protocolo HTTP según el verbo HTTP específico al que se asigna el método de la API. Para obtener más información, consulta la especificación del Protocolo de transferencia de hipertexto y la RFC del método PATCH.
Los métodos seguros, como GET y HEAD de HTTP, no deberían representar una acción que no sea de recuperación. En particular, GET de HTTP debe considerarse seguro y no tener efectos secundarios visibles para el cliente.
En HTTP, Idempotencia significa que los efectos secundarios de múltiples solicitudes idénticas son los mismos que para una sola solicitud. GET, PUT y DELETE son los métodos HTTP idempotentes relevantes a la guía de estilo. Ten en cuenta que la idempotencia solo se expresa en términos de efectos secundarios del servidor y no especifica nada sobre la respuesta. En particular, DELETE para recursos no existentes debería mostrar 404 (Not Found).
POST y PATCH de HTTP no son seguros ni idempotentes (PATCH se incluyó en la RFC 5789).
| Verbo HTTP | Seguro | Idempotente |
|---|---|---|
GET |
Sí | Sí |
PUT |
Sí | |
DELETE |
Sí | |
POST |
||
PATCH |
Formatos de carga útil
La solicitud y la respuesta deben compartir el mismo Content-Type, excepto cuando la solicitud es
GEToPOSTcon un cuerpo “application/x-www-form-urlencoded”.JSON es compatible con el tipo de MIME
application/json. El mapeo de proto3 a JSON se especifica de manera formal en Mapeo de JSON.Los parámetros de forma (
POST) pueden usarse en lugar de parámetros de consulta de URL (GET) con la misma regla de asignación de estilo REST para asignar campos de solicitud a parámetros de consulta. ElContent-Typecompatible esapplication/x-www-form-urlencoded.
Transmisión
En esta sección, se detalla cómo las APIs de Google controlan la transmisión de clientes y servidores, y se abordan específicamente las restricciones de la comunicación semidúplex en comparación con la dúplex completa, así como los requisitos de codificación para los mensajes JSON transmitidos.
Dúplex medio frente a dúplex completo
HTTP es un protocolo de solicitud y respuesta que permite que su cuerpo de solicitud o respuesta se entregue en diferentes transportes orientados a transmisiones, como TCP (HTTP/1.x) o sus variantes multiplexadas (SPDY, HTTP/2, QUIC).
Como un desarrollador de clientes, tu aplicación puede producir el cuerpo de la solicitud en modo de transmisión, es decir, una transmisión del cliente. Asimismo, la aplicación puede consumir el cuerpo de la respuesta en modo de transmisión, es decir, una transmisión del servidor.
Sin embargo, la especificación HTTP no indica si un servidor puede transmitir de vuelta el cuerpo de la respuesta (excepto por las respuestas de error) cuando el cuerpo de la solicitud todavía está pendiente. Esta semántica se conoce como transmisión de dúplex completo. Si bien muchos programas de software de cliente, servidor o proxy HTTP admiten la transmisión de dúplex completo, incluso para HTTP/1.1, las APIs de Cloud basadas en HTTP se restringen a la transmisión de dúplex medio a fin de evitar problemas de interoperabilidad.
De manera predeterminada, los métodos de transmisión con oferta en las API de Cloud suponen la semántica de dúplex completo. Es decir, no es seguro usar HTTP para invocar este método. Si un método de transmisión es solo de dúplex medio (según lo aplica el servidor), el documento de la API debe especificar con claridad el comportamiento del dúplex medio.
En el caso de los clientes de navegadores, las semánticas de HTTP estándar están restringidas por las API de la red del navegador. Los navegadores admiten la transmisión de servidores (que generalmente respeta el enmarcado a nivel de transporte) con XHR o Fetch. La API de Fetch usa transmisiones whatwg.
Debido a las restricciones del navegador, las API de Cloud que requieren compatibilidad con navegadores deben evitar la transmisión de clientes, además de la transmisión de dúplex completo, o proporcionar una API separada específica para los clientes del navegador.
En términos generales, la transmisión del cliente en Internet es menos útil que la transmisión del servidor. Esto se debe a que usar la transmisión del cliente a menudo lleva a un servicio con estado, que afecta de manera adversa el balanceo de cargas y hace que el sistema sea más vulnerable a fallas o ataques. Por otro lado, la transmisión del servidor puede ser útil, ya que puede reducir de forma significativa la latencia en las redes con demoras prolongadas de RTT.
Codificación de mensajes
Cuando se transmiten mensajes JSON, se codifican como un arreglo de mensajes JSON. El cuerpo de solicitud o respuesta se mantendrá como un tipo MIME JSON válido.
A continuación, se muestra un ejemplo de codificación de transmisión del cliente:
1 <length> <message-bytes> 1 <length> <message-bytes> … EOF
A continuación, se muestra un ejemplo de codificación de transmisión del servidor:
1 <length> <message-bytes> … 2 <length> <status-bytes> EOF
Codificación a nivel de conexión: La definición de StreamBody solo es significativa en la asignación de los IDs de etiquetas para los campos “mensajes” y “estado” <length>, que se codificarán con varint con 1 o 2 bytes para mensajes normales, por lo que la sobrecarga total de codificación es de 2 o 3 bytes por mensaje.
Se necesita un campo de relleno opcional para admitir transmisiones codificadas en base64:
message StreamBody {
repeated bytes message = 1;
google.rpc.Status status = 2;
repeated bytes padding = 15; // max one-byte tag-id: xxx01111
}
Los mensajes de error deben anexarse como el último elemento del arreglo JSON o protobuf en el mismo formato que los mensajes regulares.
Administración de estado
El comportamiento de cierre parcial se encuentra bien definido en cualquier versión HTTP para que los clientes o servidores avisen al otro extremo que el cuerpo está completo.
En particular, el código del cliente está libre para completar la solicitud mientras espera la respuesta. De manera similar, un cliente puede ver una respuesta completa cuando el cuerpo de la solicitud aún está en proceso de escritura en el servidor. El HTTP estándar espera que el cliente anule o cancele por completo la solicitud cuando una respuesta se completa de forma inesperada, por lo general, con un estado de error. Es decir, en condiciones normales, el servidor no debe completar una respuesta cuando el cliente todavía está en proceso de enviar la solicitud.
Cancelación
La compatibilidad con la cancelación le permite al cliente anular una solicitud cuando esta o la respuesta están pendientes.
No hay una compatibilidad con la cancelación confiable para los clientes de HTTP/1.*, ya que el cliente tiene la libertad de cerrar una conexión TCP luego de que se complete la solicitud sin anular la transacción de solicitud o respuesta. TCP FIN, en HTTP/1.1, no debe interpretarse como una cancelación, incluso cuando la conexión está marcada como keep-alive (Conexión: Keep-Alive).
Sin embargo, luego de que el cliente cierra la conexión TCP, si el servidor intenta escribir datos al cliente, se generará un RST, que puede activar una cancelación.
También ten en cuenta que la cancelación es un problema para las API que no transmiten. Esto sucede en particular cuando la respuesta incluye un sondeo largo y, por lo tanto, la conexión puede mantenerse inactiva por un período extendido.
La cancelación explícita es compatible con SPDY, HTTP/2 y QUIC, principalmente con el mensaje GOAWAY.
Keep-alive
La compatibilidad con keep-alive permite que el cliente o el servidor detecten un intercambio de tráfico con errores, incluso en pérdidas del paquete y fallas de la red.
No hay compatibilidad con keep-alive en HTTP/1.1 ya que keep-alive de TCP no es un enfoque viable.
QUIC o HTTP/2 ofrecen mensajes de control especiales para la implementación de la asistencia de keep-alive en aplicaciones, incluidos los navegadores.
Sin embargo, es probable que la detección de fallas y una conexión keep-alive confiable necesiten una biblioteca cliente con la compatibilidad debida del lado del servidor: las transmisiones de larga duración en Internet por lo general son propensas a errores cuando dependen de HTTP básico como protocolo de comunicación.
Control de flujo
La compatibilidad con el control de flujo requiere que el cliente propague eventos de control de flujo a nivel de transporte en la aplicación cliente. El mecanismo depende del estilo de la API del cliente de HTTP que tu aplicación cliente use. Por ejemplo, necesitas bloqueos de lectura y escritura, o bien operaciones de lectura y escritura de no bloqueo con compatibilidad explícita con el control de flujo para que las aplicaciones administren y respeten eventos de control de flujo a fin de prevenir que el cliente o el servidor se sobrecarguen.
HTTP/1.1 depende del control de flujo TCP.
SPDY y HTTP/2 tienen su propio control de flujo a nivel de transmisión, que está sujeto aún más al control de flujo TCP a nivel de conexión mientras las solicitudes se multiplexan en una sola conexión TCP.
QUIC se ejecuta en UDP y, por lo tanto, administra el control de flujo por cuenta propia.