HTTP-Richtlinien

In diesem Dokument wird erläutert, wie Google APIs mit verschiedenen HTTP-Versionen und -Implementierungen funktionieren. Wenn Sie unsere automatisch generierten oder manuell erstellten Clientbibliotheken verwenden (der empfohlene Ansatz für die meisten Anwendungsfälle), müssen Sie sich keine Gedanken über diese Details machen. Die Bibliotheken übernehmen automatisch die Low-Level-Kommunikation mit dem Server.

Wenn Sie als erfahrener Entwickler benutzerdefinierten Code schreiben, um über einen HTTP-Client eines Drittanbieters auf die REST-Schnittstelle einer API zuzugreifen, sollten Sie die hier dokumentierten relevanten Konzepte sowie die Funktionen der von Ihnen ausgewählten HTTP-Bibliothek kennen.

Verbindungsprotokolle (HTTP/*) verwenden

In diesem Abschnitt werden die unterstützten Verbindungsprotokolle – in der Regel eine HTTP-Version – erläutert, die Google APIs für die Kommunikation zwischen Clients und Servern verwenden können. Außerdem erhalten Sie Empfehlungen hinsichtlich ihrer Verwendung.

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 HTTP-Standardfunktionen sowie deren abwärtskompatible Versionen.

Die von den serverseitigen API-Implementierungen zu verarbeitende HTTP-Protokollsemantik 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 jedes HTTP/*-Protokoll verwenden, das von der Clientplattform oder ihrem clientseitigen Netzwerk zugelassen oder mit dem serverseitigen Proxy ausgehandelt wird. 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 HTTP-Protokollversionen unterstützt. Manche werden nur mit HTTP/2 und HTTP/3 vollständig angegeben, wie etwa Vollduplex-Multiplex-Streaming. Beachten Sie die Einschränkungen verschiedener HTTP-Versionen, wenn Sie eine dieser Funktionen im Rahmen der API-Spezifikation benötigen. Ältere Funktionen wie HTTP/2 Server Push sind veraltet und werden von modernen Webclients nicht unterstützt.

Generell empfehlen wir aufgrund der erhöhten Leistung, der reduzierten Blockierung der Hauptleitung und der Robustheit gegenüber Netzwerkausfällen HTTP/3 oder HTTP/2.

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-Proxys (GFE) im Namen des Serverprozesses beendet werden.

HTTP/1.1-Clients: Wenn Sie HTTP/1.1 verwenden, verwenden Sie TCP-Verbindungen immer wieder (Keep-Alive-Verbindung). 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-Blockierungen der Hauptleitung ü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 auf eine API über HTTPS oder HTTP zugreifen, wie von der API-Spezifikation unterstützt. TLS-Aushandlung 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.

Für den HTTP-Text wird ein JSON-Array verwendet, um gestreamte RPC-Methoden zu unterstützen. Das JSON-Array kann eine beliebige Anzahl von JSON-Nachrichten oder eine JSON-Meldung zum Fehlerstatus enthalten.

Lange Anfrage-URLs

Für URLs gilt eine praktikable Längenbeschränkung, die standardmäßig auf 16 KB festgelegt ist. Dies kann jedoch je nach Server variieren. Wenn die 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 diese Einschränkung zu umgehen, sollte der Clientcode eine POST-Anfrage mit dem Inhaltstyp 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. Dabei muss jede API-Methode den Anforderungen des HTTP-Protokolls basierend auf dem jeweiligen HTTP-Verb entsprechen, dem die API-Methode zugeordnet ist. Weitere Informationen finden Sie in der Hypertext Transfer Protocol Spezifikation und im RFC zur PATCH-Methode.

Sichere Methoden wie die HTTP-Methoden GET und HEAD dürfen nur das Abrufen ausführen. 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 DELETE sollte für nicht vorhandene Ressourcen 404 (Not Found) zurückgeben.

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 den gleichen Inhaltstyp haben, es sei denn, die Anfrage ist eine GET- oder POST-Anfrage mit einem application/x-www-form-urlencoded-Text.

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

  • Sie können anstelle von URL-Suchparametern (GET) auch Formularparameter (POST) verwenden. Befolgen Sie dabei die REST-Zuordnungsregeln, mit denen Anfragefelder Suchparametern zugeordnet werden. 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 in einem Streaming-Modus (Server-Streaming) verarbeiten.

Die HTTP-Spezifikation gibt jedoch nicht an, ob ein Server einen Antworttext, bei dem es sich nicht um eine Fehlerantwort handelt, zurückübermitteln darf, während der Anfragetext noch aussteht. Diese Semantik wird als Vollduplex-Streaming bezeichnet. Zahlreiche HTTP-Client/Server/Proxy-Softwareanwendungen lassen das Vollduplex-Streaming selbst für HTTP/1.1 zu. Um jedoch Interoperabilitätsprobleme zu vermeiden, sind HTTP-basierte Cloud APIs ausschließlich 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 im Allgemeinen das 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.

Generell ist das Client-Streaming über das Internet weniger effizient als das Server-Streaming. Dies liegt daran, dass das Client-Streaming oft zu einem zustandsorientierten Dienst führt, der den Lastenausgleich beeinträchtigt und das System für Fehler oder Angriffe anfälliger macht. Server-Streaming hingegen kann hilfreich sein, da es die Latenz bei Netzwerken mit langen RTT-Verzögerungen potenziell erheblich reduziert.

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 der Verbindungsebene: Die Definition von StreamBody ist nur hinsichtlich der Zuordnung von Tag-IDs von Bedeutung, da die Felder „messages“ und „status“ <length> als Varianten mit 1–2 Byte für normale Nachrichten codiert werden. Der Gesamtaufwand für die Codierung liegt somit bei 2–3 Byte pro Nachricht.

Um base64-codierte Streams zu unterstützen, ist ein optionales Füllfeld erforderlich:

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 vollständige Antwort erhalten, während der Anfragetext noch an 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. Das heißt, der Server sollte eine Antwort unter normalen Bedingungen nicht abschließen, während die Anfrage noch vom Client übermittelt wird.

Stornierung

Ein Client kann eine Anfrage stornieren, wenn die Anfrage oder die Antwort noch aussteht.

Für HTTP/1.*-Clients besteht keine zuverlässige Unterstützung der Stornierungsfunktion, da ein Client eine TCP-Verbindung nach Abschluss der Anfrage schließen kann, ohne die Anfrage/Antwort-Transaktion abzubrechen. Eine TCP FIN-Meldung sollte unter HTTP/1.1 nicht als Stornierung betrachtet werden, selbst wenn die Verbindung als Keep-Alive-Verbindung markiert wurde (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 gilt speziell, wenn die Antwort eine lange Abfrage erfordert und die Verbindung daher möglicherweise über einen längeren Zeitraum inaktiv ist.

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 und HTTP/2 bieten spezielle Kontrollmeldungen für die Implementierung von Keep-Alive-Unterstützung durch Anwendungen, einschließlich Browser.

Für eine zuverlässige Keep-Alive-Unterstützung und Fehlererkennung ist jedoch meist eine Clientbibliothek mit serverseitiger Unterstützung erforderlich. Langwierige Streaming-Prozesse über das Internet, die auf einem einfachen HTTP-Kommunikationsprotokoll basieren, sind oft fehleranfällig.

Ablaufsteuerung

Um die Ablaufsteuerung zu unterstützen, muss der Client Ablaufsteuerungsereignisse auf der Transportebene an die Clientanwendung übertragen. Der tatsächliche Mechanismus hängt vom Stil der HTTP-Client-API ab, die von Ihrer Clientanwendung verwendet wird. Um eine Überlastung des Clients oder Servers zu verhindern, benötigen Sie beispielsweise blockierende Schreib- und Lesevorgänge oder nicht blockierende Lese- und Schreibvorgänge mit expliziter Unterstützung der Ablaufsteuerung, damit Anwendungen Ablaufsteuerungsereignisse verarbeiten und respektieren.

HTTP/1.1 erfordert eine TCP-Ablaufsteuerung.

SPDY und HTTP/2 verfügen über eine eigene Ablaufsteuerung auf Stream-Ebene. Wenn mehrere Anfragen gleichzeitig über eine einzelne TCP-Verbindung übermittelt werden, unterliegt diese wiederum der TCP-Ablaufsteuerung auf der Verbindungsebene.

QUIC wird unter UDP ausgeführt und verwaltet die Ablaufsteuerung daher vollkommen eigenständig.