HTTP-Richtlinien

Wenn Sie benutzerdefinierten Code schreiben, der über einen HTTP-Client eines Drittanbieters auf die REST-Schnittstelle einer API zugreift, ist es wichtig zu wissen, wie Google APIs mit verschiedenen HTTP-Versionen und -Implementierungen funktionieren. Für die meisten Arbeitslasten empfehlen wir stattdessen die Verwendung der von Google empfohlenen Clientbibliotheken, die die in diesem Dokument beschriebene Serverkommunikation auf niedriger Ebene automatisch verarbeiten.

Verbindungsprotokolle (HTTP/*) verwenden

In diesem Abschnitt werden die unterstützten Verbindungsprotokolle (in der Regel eine Version von HTTP) beschrieben, die Google APIs für die Kommunikation zwischen Clients und Servern verwenden können. Außerdem wird erläutert, wie Sie sie am besten verwenden.

HTTP-Semantik

Halten Sie sich bei der Entwicklung von API-Clientcode an die standardmäßige HTTP-Protokoll semantik. Serverseitige Proxys oder API-Stacks unterstützen möglicherweise nur eine Teilmenge der Standard-HTTP-Funktionen und auch ihre abwärtskompatiblen Versionen.

Die HTTP-Protokollsemantik, die von den serverseitigen Implementierungen von APIs verarbeitet werden muss, wird vom Server-Stack gesteuert. Verwenden Sie eine derartige Semantik nur, wenn diese Funktionen – wie etwa das Zwischenspeichern von Daten – explizit im Rahmen der API-Spezifikation dokumentiert sind.

HTTP-Versionen

Clients können alle HTTP/*-Protokolle verwenden, die von der Clientplattform oder ihrem clientseitigen Netzwerk zugelassen oder mit dem serverseitigen Proxy ausgehandelt wurden. Zu den unterstützten Protokollen gehören HTTP/1.1, HTTP/2 und HTTP/3 (QUIC). Die Legacy-Unterstützung für HTTP/1.0 wird dringend abgeraten.

Einige API-Funktionen werden möglicherweise nur von neueren Versionen von HTTP-Protokollen unterstützt. Einige sind nur mit HTTP/2 und HTTP/3 vollständig spezifiziert, z. B. Vollduplex-Multiplex-Streaming. Beachten Sie die Einschränkungen der verschiedenen HTTP-Versionen, wenn Sie eine dieser Funktionen als Teil der API-Spezifikation benötigen. Ältere Funktionen wie HTTP/2 Server Push sind veraltet und werden von modernen Webclients nicht unterstützt.

Im Allgemeinen empfehlen wir HTTP/3 oder HTTP/2 für eine bessere Leistung, eine geringere Head-of-Line-Blockierung und eine höhere Ausfallsicherheit bei Netzwerkfehlern.

Kanäle

Kanäle beziehen sich auf die Netzwerkverbindungen der Schicht 4, die in der Regel TCP-Sockets für HTTP/1.1 und HTTP/2 und UDP-Sockets für HTTP/3 (QUIC) sind. Clientanwendungen sollten keine Annahmen darüber treffen, wie Kanäle End-to-End verwaltet werden, da Verbindungen fast immer von Google Front End (GFE)-Proxys im Namen des Serverprozesses beendet werden.

HTTP/1.1-Clients: Wenn Sie HTTP/1.1 verwenden, verwenden Sie immer TCP-Verbindungen wieder (Connection: Keep-Alive). HTTP-Clientbibliotheken verwalten in der Regel einen Verbindungspool, um die Wiederverwendung zu erleichtern. Vermeiden Sie HTTP-Pipelining bei HTTP/1.1-Verbindungen. Es wird schlecht unterstützt und kann zu Problemen führen. Weitere Informationen finden Sie unter HTTP und TCP.

HTTP/2- und HTTP/3-Clients: Moderne Clients und Browser verwenden hauptsächlich HTTP/2 oder HTTP/3. Beide Protokolle unterstützen Multiplexing, sodass mehrere Anfragen und Antworten gleichzeitig über eine einzelne Verbindung übertragen werden können.

  • HTTP/2: verwendet eine einzelne TCP-Verbindung pro Ursprung.
  • HTTP/3: verwendet eine einzelne QUIC-Verbindung über UDP pro Ursprung. QUIC integriert TLS-Verschlüsselung, Überlastungskontrolle und Verbindungsverwaltung und bietet oft Vorteile wie eine schnellere Verbindungsherstellung (0-RTT oder 1-RTT) und Unempfindlichkeit gegenüber TCP-Head-of-Line-Blockierung über Streams hinweg.

Bei HTTP/2 und HTTP/3 sind Browserlimits für die Anzahl paralleler TCP-Verbindungen zu einem einzelnen Host (z. B. 2–10) kein primäres Leistungsproblem mehr. Beachten Sie jedoch, dass Server (oder Proxys wie GFE) weiterhin Limits für die maximale Anzahl gleichzeitiger Streams innerhalb einer einzelnen HTTP/2- oder HTTP/3-Verbindung erzwingen können. Dadurch wird eine Überlastung verhindert und eine faire Ressourcennutzung gewährleistet (z. B. durch Begrenzung gleichzeitiger Anfragen oder Streams pro Verbindung auf 100).

HTTPS

Clients können über HTTPS oder HTTP auf eine API zugreifen, je nach Unterstützung durch die API-Spezifikation. TLS-Verhandlung und TLS-Versionen sind für Clientanwendungen transparent. Google APIs akzeptieren standardmäßig nur HTTPS-Traffic.

Anfrage- und Antwortformate

In diesem Abschnitt wird die Struktur von API-Interaktionen beschrieben, einschließlich der Verwendung von URL-codierten Daten, spezifischen HTTP-Methoden für RESTful-Aktionen und JSON-basierten Nutzlastformaten.

Anfrage-URLs

Die JSON-REST-Zuordnung unterstützt URL-codierte Anfragedaten und der HTTP-Anfrage- bzw. Antworttext verwendet application/json als Content-Type.

Der HTTP-Text verwendet ein JSON-Array, um gestreamte RPC-Methoden zu unterstützen. Das JSON-Array kann eine beliebige Anzahl von JSON-Nachrichten oder eine JSON-Nachricht mit Fehlerstatus enthalten.

Lange Anfrage-URLs

Die URL hat eine praktische Längenbegrenzung, die standardmäßig auf 16 KB festgelegt ist. Dies kann jedoch je nach Server variieren. Wenn Ihre API GET-Anfragen mit URLs verwendet, die diese Länge überschreiten, erreichen die Anfragen möglicherweise nicht den Ziel-API-Server und werden vom Google Front End (GFE) mit der Fehlermeldung Your client has issued a malformed or illegal request. abgelehnt.

Um die Begrenzung zu umgehen, sollte der Clientcode eine POST-Anfrage mit dem Content-Type application/x-www-form-urlencoded zusammen mit dem HTTP-Header X-HTTP-Method-Override: GET verwenden. Dieser Ansatz kann auch für DELETE-Anfragen verwendet werden.

HTTP-Methoden (Verben)

Wenn die Anfrage-URLs dem REST-Modell folgen, werden ihre HTTP-Methoden im Rahmen der API-Spezifikation angegeben. Insbesondere muss jede API-Methode die Anforderungen des HTTP-Protokolls basierend auf dem spezifischen HTTP-Verb erfüllen, dem die API-Methode zugeordnet ist. Weitere Informationen finden Sie in der Hypertext Transfer Protocol Spezifikation und im PATCH Method RFC.

Sichere Methoden wie HTTP GET und HEAD sollten keine andere Aktion als das Abrufen darstellen. Insbesondere die HTTP-Methode GET muss sicher sein und darf keine für den Client sichtbaren Nebeneffekte haben.

Idempotenz in HTTP bedeutet, dass die Nebeneffekte mehrerer identischer Anfragen die gleichen sind wie bei einer einzelnen Anfrage. GET, PUT und DELETE sind die idempotenten HTTP-Methoden, die gemäß Styleguide relevant sind. Idempotenz wird nur bezüglich der serverseitigen Nebeneffekte ausgedrückt und sagt nichts über die Antwort aus. Insbesondere sollte DELETE für nicht vorhandene Ressourcen zurückgeben 404 (Not Found).

HTTP POST und PATCH sind weder sicher noch idempotent. PATCH wurde in RFC 5789 eingeführt.

HTTP-Verb Sicher Idempotent
GET Ja Ja
PUT   Ja
DELETE   Ja
POST  
PATCH  

Nutzlastformate

  • Anfrage und Antwort sollten denselben Content-Type haben, außer wenn die Anfrage eine GET- oder eine POST-Anfrage mit einem Text vom Typ application/x-www-form-urlencoded ist.

  • JSON wird unter dem MIME-Typ application/json unterstützt. Die Zuordnung von proto3 zu JSON wird formal in der JSON Zuordnung festgelegt.

  • Formularparameter (POST) können anstelle von URL-Suchparametern (GET) verwendet werden. Dabei gilt dieselbe REST-Zuordnungsregel für die Zuordnung von Anfragefeldern zu Suchparametern. Der unterstützte Content-Type ist application/x-www-form-urlencoded.

Streaming

In diesem Abschnitt wird beschrieben, wie Google APIs Client- und Server-Streaming verarbeiten. Dabei werden insbesondere die Einschränkungen der Halbduplex- und Vollduplex-Kommunikation sowie die Codierungsanforderungen für gestreamte JSON-Nachrichten behandelt.

Halbduplex und Vollduplex im Vergleich

HTTP ist ein Anfrage/Antwort-Protokoll, dessen Anfrage- oder Antworttext über unterschiedliche streamorientierte Transportprotokolle wie TCP (HTTP/1.x) oder die Multiplex-Varianten SPDY, HTTP/2 bzw. QUIC übermittelt werden kann.

Als Cliententwickler kann Ihre Anwendung den Anfragetext in einem Streaming-Modus (Client-Streaming) generieren. Ebenso kann die Anwendung den Antworttext auch in einem Streaming-Modus (Server-Streaming) verarbeiten.

Die HTTP-Spezifikation legt jedoch nicht fest, ob ein Server den Antworttext (außer bei Fehlermeldungen) streamen darf, wenn der Anfragetext noch aussteht. Diese Semantik wird als Vollduplex-Streaming bezeichnet. Obwohl viele HTTP-Client-/Server-/Proxy-Softwareprogramme Vollduplex-Streaming zulassen, auch für HTTP/1.1, sind HTTP-basierte Cloud APIs aus Gründen der Interoperabilität nur auf Halbduplex-Streaming beschränkt.

Standardmäßig setzen Bidi-Streaming-Methoden in Cloud APIs die Vollduplex-Semantik voraus. Es gilt also als nicht sicher, wenn Sie HTTP zum Aufrufen einer solchen Methode verwenden. Wenn eine Streaming-Methode nur Halbduplex ist (wie vom Server erzwungen), sollte das API-Dokument das Halbduplex-Verhalten eindeutig festlegen.

Bei Browserclients wird die Standard-HTTP-Semantik durch die Netzwerk-APIs des Browsers weiter eingeschränkt. Browser unterstützen Server-Streaming (das in der Regel die Framing auf Transportebene berücksichtigt) über XHR oder Fetch. Die Fetch API verwendet whatwg-Streams.

Aufgrund von Browsereinschränkungen müssen Cloud APIs, die eine Browserunterstützung erfordern, sowohl ein Client-Streaming als auch ein Vollduplex-Streaming vermeiden oder eine separate API speziell für Browserclients bereitstellen.

Im Allgemeinen ist Client-Streaming über das Internet weniger nützlich als Server-Streaming. Das liegt daran, dass die Verwendung von Client-Streaming oft zu einem zustandsbehafteten Dienst führt, was sich negativ auf den Lastenausgleich auswirkt und das System anfälliger für Fehler oder Angriffe macht. Server-Streaming kann hingegen nützlich sein, da es die Latenz in Netzwerken mit langen RTT-Verzögerungen erheblich reduzieren kann.

Nachrichtencodierung

JSON-Nachrichten werden während der Übertragung als Array von JSON-Nachrichten codiert. Der Anfrage- oder Antworttext bleibt ein gültiger JSON MIME-Typ.

Beispiel für die Codierung von Client-Streams:

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

Beispiel für die Codierung von Server-Streams:

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

Codierung auf Verbindungsebene: Die Definition von StreamBody ist nur in Bezug auf die Zuweisung von Tag-IDs für die Felder „messages“ und „status“ <length> von Bedeutung. Diese werden mit 1–2 Byte für normale Nachrichten varint-codiert, sodass der gesamte Codierungs aufwand 2–3 Byte pro Nachricht beträgt.

Ein optionales Padding-Feld ist erforderlich, um base64-codierte Streams zu unterstützen:

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

Fehlermeldungen sollten dem letzten Element des JSON- oder protobuf-Arrays angehängt werden und dasselbe Format wie reguläre Meldungen haben.

Zustandsverwaltung

Das halbgeschlossene Verhalten ist in HTTP-Versionen gut für Clients oder Server definiert. Damit wird dem anderen Ende signalisiert, dass der Text vollständig ist.

Speziell Anfragen, die noch auf die Antwort warten, können mit Clientcode abgeschlossen werden. Ebenso kann ein Client eine abgeschlossene Antwort sehen, während der Anfragetext noch auf den Server geschrieben wird. Wenn eine Antwort auf unerwartete Weise abgeschlossen wird, erwartet HTTP standardmäßig, dass der Client die Anfrage – in der Regel mit einem Fehlerstatus – abbricht oder abschließt. Unter normalen Umständen sollte der Server also keine Antwort abschließen, während der Client noch die Anfrage sendet.

Stornierung

Die Unterstützung für Stornierungen ermöglicht es einem Client, eine Anfrage abzubrechen, wenn die Anfrage oder Antwort noch aussteht.

Für HTTP/1.*-Clients gibt es keine zuverlässige Unterstützung für Stornierungen, da ein Client eine TCP-Verbindung nach Abschluss der Anfrage schließen kann, ohne die Anfrage- oder Antworttransaktion abzubrechen. Ein TCP-FIN sollte unter HTTP/1.1 nicht als Stornierung interpretiert werden, auch wenn die Verbindung als Keep-Alive-Verbindung gekennzeichnet ist (Connection: Keep-Alive).

Nachdem der Client die TCP-Verbindung jedoch geschlossen hat, wird eine RST-Antwort generiert, wenn der Server versucht, Daten an den Client zu schreiben. Dies kann eine Stornierung auslösen.

Stornierungen sind auch bei Nicht-Streaming-APIs ein Thema. Dies ist insbesondere der Fall, wenn die Antwort ein Long Polling beinhaltet und die Verbindung daher möglicherweise längere Zeit im Leerlauf bleibt.

Explizite Stornierungen werden durch SPDY, HTTP/2 und QUIC unterstützt, speziell mit der go-away-Nachricht.

Keep-Alive

Durch Keep-Alive-Unterstützung kann ein Client oder Server einen fehlerhaften Peer selbst bei einem Paketverlust oder Netzwerkausfall erkennen.

In HTTP/1.1 wird Keep-Alive nicht unterstützt, da TCP-Keep-Alive keinen praktikablen Ansatz darstellt.

QUIC oder HTTP/2 bieten spezielle Steuernachrichten, um die Keep-Alive-Unterstützung durch Anwendungen, einschließlich Browser, zu implementieren.

Für eine zuverlässige Keep-Alive- und Fehlererkennung ist jedoch wahrscheinlich eine Clientbibliothek mit der erforderlichen serverseitigen Unterstützung erforderlich. Langlebiges Streaming über das Internet ist oft fehleranfällig, wenn grundlegendes HTTP als Kommunikationsprotokoll verwendet wird.

Ablaufsteuerung

Die Unterstützung für die Ablaufsteuerung erfordert, dass der Client Ereignisse der Ablaufsteuerung auf Transportebene an die Clientanwendung weiterleitet. Der tatsächliche Mechanismus hängt vom Stil der HTTP-Client-API ab, die von Ihrer Clientanwendung verwendet wird. Sie benötigen beispielsweise blockierende Schreib- und Lesevorgänge oder nicht blockierende Lese- und Schreibvorgänge mit expliziter Unterstützung für die Ablaufsteuerung, damit Anwendungen Ereignisse der Ablaufsteuerung verarbeiten und berücksichtigen können, um eine Überlastung des Clients oder Servers zu verhindern.

HTTP/1.1 erfordert eine TCP-Ablaufsteuerung.

SPDY und HTTP/2 haben eine eigene Ablaufsteuerung auf Stream-Ebene, die zusätzlich der TCP-Ablaufsteuerung auf Verbindungsebene unterliegt, da Anfragen über eine einzelne TCP-Verbindung gemultiplext werden.

QUIC wird über UDP ausgeführt und verwaltet daher die Ablaufsteuerung vollständig selbst.