Este documento descreve como as APIs Google funcionam com diferentes versões e implementações HTTP. Se estiver a usar uma das nossas bibliotecas de cliente geradas ou criadas manualmente (a nossa abordagem recomendada para a maioria dos exemplos de utilização), não tem de se preocupar com isto, uma vez que o código fornecido lida com os problemas de baixo nível de comunicação com o servidor.
No entanto, se for um programador experiente e precisar de escrever o seu próprio código personalizado para aceder diretamente à interface REST de uma API através de uma biblioteca de cliente HTTP de terceiros à sua escolha, deve compreender, pelo menos, algumas das semânticas documentadas aqui (conforme relevante para a API escolhida), bem como compreender o que é fornecido pela sua biblioteca HTTP.
Trabalhar com protocolos de rede (HTTP/*)
Esta secção descreve os protocolos de rede suportados (normalmente, uma versão do HTTP) que as APIs Cloud podem usar para comunicar entre clientes e servidores, e como recomendamos que os use. Vamos analisar os detalhes da forma como os pedidos e as respostas estão estruturados na secção seguinte abaixo.
Semântica HTTP
Ao desenvolver código de cliente da API, siga a semântica do protocolo HTTP padrão. Os proxies do lado do servidor ou as pilhas de APIs podem suportar apenas um subconjunto de funcionalidades HTTP padrão e também podem suportar as respetivas versões retrocompatíveis.
A semântica do protocolo HTTP que tem de ser processada pelas implementações do lado do servidor das APIs é controlada pela pilha do servidor. Apenas confie em semânticas deste tipo se estas funcionalidades estiverem explicitamente documentadas como parte da especificação da API, como o suporte de colocação em cache.
Versões HTTP
Os clientes podem usar quaisquer protocolos HTTP/*, conforme permitido pela plataforma do cliente ou pela respetiva rede do lado do cliente, ou conforme negociado com o proxy do lado do servidor. Os protocolos suportados incluem HTTP/1.0, HTTP/1.1, SPDY/*, HTTP/2 e QUIC.
Algumas funcionalidades da API podem ser suportadas apenas por versões mais recentes de protocolos HTTP, como o envio por push do servidor e as prioridades. Algumas só são totalmente especificadas com o HTTP/2, como o streaming full-duplex. Tenha em atenção as limitações das diferentes versões HTTP se precisar de alguma destas funcionalidades como parte da especificação da API.
Geralmente, também recomendamos o HTTP/2 para um melhor desempenho, bem como resiliência a falhas de rede.
Canais
Os canais referem-se às ligações de rede L4 (sockets TCP ou UDP). As aplicações cliente não devem fazer nenhuma suposição sobre como os canais são usados no tempo de execução para publicar pedidos HTTP. Em quase todos os casos, os canais são terminados por proxies em nome do processo do servidor.
Para clientes HTTP/1.1, reutilize sempre as ligações TCP (Connection: Keep-Alive). É provável que a biblioteca de clientes HTTP também faça a gestão de um conjunto de ligações para um melhor desempenho. Não envie pedidos em pipeline através da mesma ligação TCP. Consulte HTTP e TCP para mais informações.
Todos os navegadores modernos usam SPDY/*, HTTP/2 ou QUIC, que multiplexam pedidos através de um único canal. O limite de ligação tradicional (2 a 10) nunca deve ser um problema, exceto quando a implementação do servidor limita o número de pedidos HTTP simultâneos de um único cliente, por exemplo, 100 streams HTTP/2 contra uma única origem.
HTTPS
Os clientes podem aceder a uma API através de HTTPS ou HTTP, conforme suportado pela especificação da API. A negociação de TLS e as versões de TLS são transparentes para as aplicações cliente. Por predefinição, as APIs Google só aceitam tráfego HTTPS.
Formatos de pedido/resposta
URLs de pedidos
O mapeamento JSON-REST suporta dados de pedidos codificados por URL, e o corpo do pedido e da resposta HTTP usa application/json
como Content-Type
.
O corpo HTTP usa uma matriz JSON para suportar métodos RPC transmitidos e a matriz JSON pode conter qualquer número de mensagens JSON ou uma mensagem JSON de estado de erro.
URLs de pedidos longos
O URL tem uma limitação de comprimento prática, normalmente definida como 16 KB por predefinição, embora isto possa variar consoante o servidor. Se a sua API usar pedidos GET com URLs que excedam este comprimento, os pedidos podem não chegar ao servidor da API de destino e serão rejeitados pelo front-end da Google (GFE) com a mensagem de erro Your client has issued a malformed or illegal request.
Para contornar a limitação, o código do cliente deve usar um pedido POST com o tipo de conteúdo application/x-www-form-urlencoded
, juntamente com o cabeçalho HTTP X-HTTP-Method-Override: GET
. Esta abordagem também funciona para pedidos DELETE.
Métodos HTTP (verbos)
Se os URLs de pedidos seguirem o modelo REST, os respetivos métodos HTTP são especificados como parte da especificação da API. Em particular, todos os métodos da API têm de estar em conformidade com os requisitos do protocolo HTTP com base no verbo HTTP específico ao qual o método da API é mapeado. Para ver detalhes, consulte a especificação do protocolo de transferência de hipertexto e a RFC do método PATCH.
Os métodos seguros, como HTTP GET
e HEAD
, não devem representar uma ação que não seja a obtenção. Especificamente, o HTTP GET
deve ser considerado seguro e não deve ter efeitos secundários visíveis para o cliente.
A idempotência em HTTP significa que os efeitos secundários de vários pedidos idênticos são os mesmos que os de um único pedido. GET
, PUT
e DELETE
são os métodos HTTP idempotentes relevantes para o guia de estilo. Tenha em atenção que a idempotência só é expressa em termos de efeitos secundários do servidor e não especifica nada sobre a resposta. Em particular, DELETE
para recursos inexistentes
deve devolver 404 (Not Found)
.
HTTP POST
e PATCH
não são seguros nem idempotentes. (PATCH
foi introduzido no RFC 5789)
Verbo HTTP | Seguro | Idempotente |
---|---|---|
GET |
Sim | Sim |
PUT |
Sim | |
DELETE |
Sim | |
POST |
||
PATCH |
Formatos de payload
O pedido e a resposta devem partilhar o mesmo Content-Type, exceto quando o pedido é um
GET
ou umPOST
com um corpo "application/x-www-form-urlencoded
".O formato JSON é suportado no tipo MIME
application/json
. O mapeamento de proto3 para JSON é especificado formalmente no mapeamento JSON.Os parâmetros de formulário (
POST
) podem ser usados em vez dos parâmetros de consulta de URL (GET
), seguindo a mesma regra de mapeamento no estilo REST para mapear campos de pedidos para parâmetros de consulta. OContent-Type
suportado éapplication/x-www-form-urlencoded
.
Streaming
Half-duplex versus full-duplex
O HTTP é um protocolo de pedido-resposta que permite que o respetivo corpo de pedido ou resposta seja fornecido através de diferentes transportes orientados para streams, como o TCP (HTTP/1.x) ou as respetivas variantes multiplexadas (SPDY, HTTP/2 e QUIC).
Enquanto programador de cliente, a sua aplicação pode produzir o corpo do pedido num modo de streaming, ou seja, streaming do cliente. Da mesma forma, a aplicação também pode consumir o corpo da resposta num modo de streaming, ou seja, streaming do servidor.
No entanto, a especificação HTTP não especifica se um servidor tem autorização para transmitir o corpo da resposta (exceto para respostas de erro) quando o corpo do pedido ainda está pendente. Esta semântica é conhecida como streaming full-duplex. Embora muitos softwares de cliente/servidor/proxy HTTP permitam o streaming full-duplex, mesmo para HTTP/1.1, para evitar problemas de interoperabilidade, as APIs Google Cloud baseadas em HTTP estão restritas apenas ao streaming half-duplex.
Por predefinição, os métodos de streaming bidirecional nas APIs Google Cloud assumem a semântica full-duplex. Ou seja, não é seguro usar HTTP para invocar tal método. Se um método de streaming for apenas half-duplex (conforme aplicado pelo servidor), o documento da API deve especificar claramente o comportamento half-duplex.
Para clientes de navegador, a semântica HTTP padrão é ainda mais restrita pelas APIs de rede do navegador. Atualmente, os navegadores só suportam a transmissão em fluxo do servidor (que geralmente respeita o enquadramento ao nível do transporte) através de XHR ou Fetch. A API Fetch usa streams whatwg.
Devido às restrições do navegador, as APIs Cloud que requerem suporte do navegador têm de evitar o streaming do cliente, bem como o streaming full-duplex, ou fornecer uma API separada especificamente para clientes do navegador.
Em geral, o streaming do cliente através da Internet é menos útil do que o streaming do servidor. Isto deve-se ao facto de a utilização do streaming do cliente conduzir frequentemente a um serviço com estado, o que afeta negativamente o equilíbrio de carga e torna o sistema mais vulnerável a falhas ou ataques. Por outro lado, o streaming do servidor pode ser útil, uma vez que pode reduzir significativamente a latência em redes com longos atrasos de RTT.
Codificação de mensagens
As mensagens JSON quando o streaming é codificado como uma matriz de mensagens JSON. O corpo do pedido ou da resposta permanece como um tipo MIME JSON válido.
Exemplo de codificação de stream de cliente:
1 <length> <message-bytes> 1 <length> <message-bytes> … EOF
Exemplo de codificação de stream do servidor:
1 <length> <message-bytes> … 2 <length> <status-bytes> EOF
Codificação ao nível do fio: a definição de StreamBody só é significativa na respetiva atribuição de IDs de etiquetas para o campo "messages" e "status".
É necessário um campo de preenchimento opcional para suportar streams codificadas em 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 devem ser anexadas como o último elemento da matriz JSON ou protobuf, no mesmo formato que as mensagens normais.
Gestão de estados
O comportamento de fecho parcial está bem definido em qualquer versão HTTP para um cliente ou um servidor sinalizar ao outro lado que o corpo está concluído.
Em particular, o código do cliente é livre para concluir o pedido quando ainda está a aguardar a resposta. Da mesma forma, um cliente pode ver uma resposta concluída quando o corpo do pedido ainda está a ser escrito no servidor. A norma HTTP espera que o cliente anule ou conclua o pedido quando uma resposta é concluída de forma inesperada, normalmente com um estado de erro. Isto significa que, em condições normais, o servidor não deve concluir uma resposta quando o cliente ainda está a enviar o pedido.
Cancelamento
O apoio técnico para cancelamentos permite que um cliente anule um pedido quando o pedido ou a resposta ainda estiver pendente.
Não existe suporte de cancelamento fiável para clientes HTTP/1.*, uma vez que um cliente pode fechar uma ligação TCP após a conclusão do pedido sem anular a transação de pedido/resposta. Um TCP FIN, no âmbito do HTTP/1.1, não deve ser interpretado como um cancelamento, mesmo quando a ligação está marcada como uma ligação persistente (Connection: Keep-Alive).
No entanto, depois de o cliente fechar a ligação TCP, se o servidor tentar escrever dados no cliente, é gerado um RST, que pode acionar um cancelamento.
Tenha também em atenção que o cancelamento também é um problema para APIs não de streaming. Isto acontece especialmente quando a resposta envolve uma sondagem longa e, por isso, a ligação pode ficar inativa durante um período prolongado.
O cancelamento explícito é suportado com SPDY, HTTP/2 e QUIC, nomeadamente com a mensagem go-away.
Keep-alive
O suporte de keep-alive permite que um cliente ou um servidor detete um par com falhas, mesmo em caso de perda de pacotes ou falhas de rede.
Não existe compatibilidade com keep-alive em HTTP/1.1, uma vez que o keep-alive de TCP não é uma abordagem viável.
O QUIC ou o HTTP/2 oferecem mensagens de controlo especiais para implementar o suporte de keep-alive por aplicações, incluindo navegadores.
No entanto, a deteção de falhas e a manutenção em funcionamento fiáveis vão provavelmente exigir uma biblioteca de cliente com o apoio técnico necessário do lado do servidor: a transmissão em fluxo contínuo de longa duração através da Internet é frequentemente propensa a erros quando se baseia no HTTP básico como protocolo de comunicação.
Controlo do fluxo
O suporte de controlo de fluxo requer que o cliente propague eventos de controlo de fluxo ao nível do transporte para a aplicação cliente. O mecanismo real depende do estilo da API do cliente HTTP que a sua aplicação cliente usa. Por exemplo, precisa de bloquear escritas e leituras, ou leituras e escritas sem bloqueio com suporte de controlo de fluxo explícito para que as aplicações processem e respeitem eventos de controlo de fluxo, de modo a evitar que o cliente ou o servidor fiquem sobrecarregados.
O HTTP/1.1 baseia-se no controlo de fluxo TCP.
O SPDY e o HTTP/2 têm o seu próprio controlo de fluxo ao nível da stream, que está ainda sujeito ao controlo de fluxo TCP ao nível da ligação, uma vez que os pedidos são multiplexados através de uma única ligação TCP.
O QUIC é executado no UDP e, por isso, gere o controlo de fluxo de forma totalmente autónoma.