Diretrizes HTTP

Este documento explica como as APIs do Google funcionam com várias versões e implementações HTTP. Se você usa nossas bibliotecas de cliente geradas ou criadas manualmente (a abordagem recomendada para a maioria dos casos de uso), não precisa se preocupar com esses detalhes. As bibliotecas processam automaticamente a comunicação de baixo nível com o servidor para você.

Se você for um desenvolvedor experiente que escreve código personalizado para acessar a interface REST de uma API usando um cliente HTTP de terceiros, é importante entender os conceitos relevantes documentados aqui, além dos recursos fornecidos pela biblioteca HTTP escolhida.

Como trabalhar com protocolos de transferência (HTTP/*)

Nesta seção, descrevemos os protocolos de transferência compatíveis (normalmente uma versão do HTTP) que as APIs do Google podem usar para fazer a comunicação entre clientes e servidores, e como recomendamos que você os use.

Semântica do HTTP

Ao desenvolver o código de cliente da API, siga a semântica do protocolo HTTP padrão. Os proxies do lado do servidor ou as pilhas da API podem ser compatíveis somente com um subconjunto de recursos HTTP padrão e também podem aceitar as versões compatíveis anteriores.

A semântica do protocolo HTTP que precisa ser manipulada pelas implementações do lado do servidor das APIs é controlada pela pilha do servidor. Confie nessa semântica apenas se esses recursos forem explicitamente documentados como parte da especificação da API, como o suporte ao armazenamento em cache.

Versões do HTTP

Os clientes podem usar qualquer protocolo HTTP/*, conforme permitido pela plataforma do lado do cliente ou pela respetiva rede do lado do cliente, ou conforme negociado com o proxy do lado do servidor. Os protocolos compatíveis incluem HTTP/1.1, HTTP/2 e HTTP/3 (QUIC). Não recomendamos o suporte legado para HTTP/1.0.

Alguns recursos da API podem ser compatíveis apenas com versões mais recentes de protocolos HTTP. Alguns são totalmente especificados com HTTP/2 e HTTP/3, como o streaming multiplexado full-duplex. Se você precisar de algum desses recursos como parte da especificação da API, não se esqueça das limitações das diferentes versões do HTTP. Recursos mais antigos, como o push do servidor HTTP/2, estão obsoletos e não são compatíveis com clientes da Web modernos.

Em geral, recomendamos HTTP/3 ou HTTP/2 para melhor desempenho, redução do bloqueio de início de linha e maior resiliência a falhas de rede.

Canais

Os canais se referem às conexões de rede da camada 4, que geralmente são soquetes TCP para HTTP/1.1 e HTTP/2, e soquetes UDP para HTTP/3 (QUIC). Os aplicativos clientes não devem fazer suposições sobre como os canais são gerenciados de ponta a ponta, já que as conexões quase sempre são encerradas por proxies do Google Front End (GFE) em nome do processo do servidor.

Clientes HTTP/1.1: se você estiver usando HTTP/1.1, sempre reutilize conexões TCP (Connection: Keep-Alive). As bibliotecas de cliente HTTP geralmente gerenciam um pool de conexões para facilitar a reutilização. Evite o encadeamento HTTP em conexões HTTP/1.1. Ele tem suporte ruim e pode causar problemas. Para mais informações, consulte HTTP e TCP.

Clientes HTTP/2 e HTTP/3: os clientes e navegadores modernos usam predominantemente HTTP/2 ou HTTP/3. Os dois protocolos oferecem suporte à multiplexação, permitindo que várias solicitações e respostas estejam em voo simultaneamente em uma única conexão.

  • HTTP/2: usa uma única conexão TCP por origem.
  • HTTP/3: usa uma única conexão QUIC por UDP por origem. O QUIC integra criptografia TLS, controle de congestionamento e gerenciamento de conexões, geralmente oferecendo benefícios como configuração de conexão mais rápida (0-RTT ou 1-RTT) e imunidade ao bloqueio head-of-line do TCP em fluxos.

Com o HTTP/2 e o HTTP/3, os limites do navegador no número de conexões TCP paralelas com um único host (por exemplo, de 2 a 10) não são mais uma preocupação principal de desempenho. No entanto, saiba que os servidores (ou proxies como o GFE) ainda podem impor limites no número máximo de streams simultâneos em uma única conexão HTTP/2 ou HTTP/3. Isso evita a sobrecarga e garante o uso justo de recursos (por exemplo, limitando a 100 as solicitações ou streams simultâneos por conexão).

HTTPS

Os clientes podem acessar uma API usando HTTPS ou HTTP, conforme compatibilidade com a especificação da API. A negociação TLS e as versões TLS são transparentes para aplicativos cliente. Por padrão, as APIs do Google aceitam apenas tráfego HTTPS.

Formatos de solicitação e resposta

Esta seção descreve a estrutura das interações da API, incluindo o uso de dados codificados por URL, métodos HTTP específicos para ações RESTful e formatos de payload baseados em JSON.

Solicitar URLs

O mapeamento JSON-REST é compatível com dados de solicitação codificados de URL, e a solicitação HTTP e o corpo de resposta usam application/json como Content-Type.

O corpo HTTP usa uma matriz JSON para a compatibilidade com métodos RPC em streaming, e essa matriz pode conter qualquer número de mensagens JSON ou uma mensagem JSON de status de erro.

URLs de solicitação longa

O URL tem uma limitação prática de comprimento, normalmente definida como 16 KB por padrão, mas isso pode variar dependendo do servidor. Se a sua API usa solicitações GET com URLs que excedem esse comprimento, as solicitações podem não chegar ao servidor de API de destino e serão rejeitadas pelo Google Front End (GFE) com a mensagem de erro Your client has issued a malformed or illegal request.

Para ignorar a limitação, o código do cliente precisa usar uma solicitação POST com um Content-Type de application/x-www-form-urlencoded junto com o cabeçalho HTTP X-HTTP-Method-Override: GET. Essa abordagem também funciona para solicitações DELETE.

Métodos HTTP (verbos)

Se os URLs de solicitação seguirem o modelo REST, os métodos HTTP deles serão parte da especificação da API. Em particular, cada método da API precisa cumprir os requisitos do protocolo HTTP com base no verbo HTTP específico ao qual o método da API mapeia. Para mais informações, consulte a especificação do protocolo de transferência de hipertexto e o documento RFC do método PATCH.

Métodos seguros, como GET e HEAD do HTTP, não podem ser usados para representar uma ação que não seja a recuperação. Especificamente, o GET do HTTP precisa ser considerado seguro e não pode ter nenhum efeito colateral visível para o cliente.

Idempotência em HTTP significa que os efeitos colaterais de várias solicitações idênticas são os mesmos de uma única solicitação. GET, PUT e DELETE são os métodos HTTP idempotentes relevantes para o guia de estilo. Observe que a idempotência é expressada apenas em termos de efeitos colaterais do servidor e não especifica nada sobre a resposta. Em particular, DELETE para recursos não existentes precisa retornar 404 (Not Found).

POST e PATCH HTTP não são seguros nem idempotentes (PATCH foi incluído no RFC 5789).

Verbo HTTP Seguro Idempotente
GET Sim Sim
PUT   Sim
DELETE   Sim
POST  
PATCH  

Formatos de payload

  • A solicitação e a resposta precisam compartilhar o mesmo tipo de conteúdo, exceto quando a solicitação é um GET ou um POST com um corpo "application/x-www-form-urlencoded".

  • JSON é compatível com o tipo MIME application/json. O mapeamento de proto3 para JSON é especificado formalmente em Mapeamento do JSON.

  • Parâmetros de formulário (POST) podem ser usados no lugar de parâmetros de consulta do URL (GET), seguindo a mesma regra de mapeamento de estilo REST para campos de solicitação a parâmetros de consulta. O Content-Type compatível é application/x-www-form-urlencoded.

Streaming

Esta seção detalha como as APIs do Google processam o streaming de clientes e servidores, abordando especificamente as restrições da comunicação half-duplex versus full-duplex e os requisitos de codificação para mensagens JSON transmitidas.

Half-duplex em comparação com full-duplex

O HTTP é um protocolo de solicitação-resposta que permite que o corpo de solicitação ou de resposta correspondente seja entregue em diferentes transportes orientados por stream, como TCP (HTTP/1.x) ou as variantes multiplexadas (SPDY, HTTP/2, QUIC).

Como desenvolvedor de clientes, seu aplicativo pode produzir o corpo da solicitação em um modo de streaming, ou seja, streaming de cliente. Da mesma forma, o aplicativo também pode consumir o corpo de resposta em um modo de streaming, ou seja, streaming de servidor.

No entanto, a especificação HTTP não define se um servidor pode fazer streaming do corpo da resposta (exceto para respostas de erro) quando o corpo da solicitação ainda está pendente. Essa semântica é conhecida como streaming full-duplex. Muitos softwares de cliente/servidor/proxy HTTP permitem o streaming full-duplex, mesmo para HTTP/1.1. No entanto, para evitar problemas de interoperabilidade, as APIs do Cloud baseadas em HTTP são restritas apenas ao streaming half-duplex.

Por padrão, os métodos de streaming de lances nas APIs do Cloud pressupõem a semântica full-duplex. Ou seja, não é seguro usar HTTP para invocar esse método. Se um método de streaming for somente half-duplex (conforme exigido pelo servidor), o documento da API precisará especificar claramente o comportamento half-duplex.

Para clientes de navegador, a semântica HTTP padrão é restringida pelas APIs de rede do navegador. Os navegadores são compatíveis com streaming de servidor (que geralmente respeita o enquadramento no nível de transporte) usando XHR ou Fetch. A API Fetch usa fluxos whatwg.

Devido às restrições do navegador, as APIs do Cloud que exigem suporte a navegadores precisam evitar streaming de clientes, bem como streaming full-duplex, ou fornecer uma API separada especificamente para clientes de navegador.

De modo geral, o streaming de clientes pela Internet é menos útil do que o streaming de servidor. Isso ocorre porque o uso de streaming de clientes geralmente leva a um serviço com monitoramento de estado, o que afeta negativamente o balanceamento de carga e torna o sistema mais vulnerável a falhas ou ataques. O streaming de servidor, por outro lado, pode ser útil, já que pode reduzir significativamente a latência em relação aos novatos com longos atrasos de RTT.

Codificação de mensagens

As mensagens JSON são codificadas como uma matriz no momento do streaming. O corpo de solicitação ou resposta permanecerá como um tipo JSON MIME válido.

Exemplo de codificação de streaming de cliente:

1 <length> <message-bytes> 1 <length> <message-bytes>   EOF

Exemplo de codificação de streaming de servidor:

1 <length> <message-bytes>   2 <length> <status-bytes> EOF

Codificação no nível de transferência: a definição de StreamBody só é significativa na alocação de códigos de tags para os campos "messages" e "status" <length>, que serão codificados em varint com 1 a 2 bytes para mensagens normais. Portanto, a sobrecarga total de codificação é de 2 a 3 bytes por mensagem.

Um campo de preenchimento opcional é necessário para a compatibilidade com streams codificados por base64:

message StreamBody {
  repeated bytes message = 1;
  google.rpc.Status status = 2;
  repeated bytes padding = 15;   // max one-byte tag-id: xxx01111
}

As mensagens de erro precisam ser anexadas como o último elemento da matriz protobuf ou JSON, no mesmo formato que as mensagens normais.

Gerenciamento do estado

O comportamento semifechado é bem definido em qualquer versão do HTTP para um cliente ou servidor a fim de sinalizar para a outra extremidade que o corpo está completo.

Em particular, o código de cliente estará livre para completar a solicitação quando ainda estiver aguardando a resposta. Da mesma forma, um cliente poderá ver uma resposta completa quando o corpo da solicitação ainda estiver sendo gravado no servidor. O padrão HTTP espera que o cliente cancele ou complete a solicitação quando uma resposta for concluída de maneira inesperada, normalmente com um status de erro. Isso significa dizer que, em condições normais, o servidor não completará uma resposta quando o cliente ainda estiver enviando a solicitação.

Cancelamento

A compatibilidade de cancelamento permite que um cliente anule uma solicitação quando ela ou a resposta ainda estiverem pendentes.

Não há compatibilidade de cancelamento confiável para clientes HTTP/1.*, uma vez que um cliente é livre para fechar uma conexão TCP depois que a solicitação tenha sido concluída sem cancelar a transação de solicitação ou resposta. Um TCP FIN, em HTTP/1.1, não será interpretado como um cancelamento, mesmo quando a conexão estiver marcada como sinal de atividade (Connection: Keep-Alive).

No entanto, depois que o cliente tiver fechado a conexão TCP, se o servidor tentar gravar qualquer dado para o cliente, um RST será gerado, o que pode acionar um cancelamento.

Observe que o cancelamento também é um problema para APIs que não são de streaming. Esse é o caso quando a resposta envolve uma sondagem longa e, consequentemente, a conexão pode ficar inativa por um período prolongado.

O cancelamento explícito é compatível com SPDY, HTTP/2 e QUIC, principalmente com a mensagem de go-away.

Keep-alive

A compatibilidade com keep-alive permite que um cliente ou servidor detecte um par com falha mesmo no caso de perda de pacotes ou falhas de rede.

Não há compatibilidade com keep-alive HTTP/1.1, já que o keep-alive do TCP não é uma abordagem viável.

O QUIC ou o HTTP/2 oferecem mensagens de controle especiais com a finalidade de implementar a compatibilidade com sinal de atividade por aplicativos, incluindo navegadores.

No entanto, uma detecção confiável de falhas e sinal de atividade provavelmente exigirá uma biblioteca de cliente com a compatibilidade necessária do lado do servidor: fazer streamings de longa duração pela Internet geralmente pode causar erros quando se confia em HTTP básico como protocolo de comunicação.

Controle de fluxo

A compatibilidade com o controle de fluxo exige que o cliente propague eventos desse tipo no nível de transporte para o aplicativo do cliente. O mecanismo real depende do estilo da API do cliente HTTP que seu aplicativo cliente usa. Por exemplo, você precisa de gravações e leituras incompatíveis ou compatíveis com versões anteriores que tenham compatibilidade com controle de fluxo explícito para aplicativos para lidar e respeitar os eventos de controle de fluxo, a fim de evitar que o cliente ou o servidor sejam sobrecarregados.

O HTTP/1.1 conta com o controle de fluxo TCP.

O SPDY e o HTTP/2 têm o próprio controle de fluxo no nível do stream, que está sujeito ao controle de fluxo TCP no nível da conexão, uma vez que as solicitações são multiplexadas em uma única conexão TCP.

O QUIC é executado no UDP. Portanto, ele gerencia integralmente o controle de fluxo por conta própria.