HTTP-Richtlinien

In diesem Dokument wird beschrieben, wie Google APIs mit verschiedenen HTTP-Versionen und -Implementierungen zusammenarbeiten. Wenn Sie eine unserer automatisch generierten oder manuell erstellten Clientbibliotheken verwenden – unser empfohlener Ansatz für die meisten Anwendungsfälle –, brauchen Sie sich darüber keine Gedanken zu machen. Der bereitgestellte Code handhabt die für die Kommunikation mit dem Server erforderlichen Details.

Wenn Sie jedoch als erfahrener Entwickler Ihren eigenen benutzerdefinierten Code schreiben möchten, um über die HTTP-Clientbibliothek eines Drittanbieters Ihrer Wahl direkt auf die REST-Schnittstelle einer API zuzugreifen, sollten Sie die hier dokumentierte Semantik zumindest für die jeweils relevante API verstehen. Außerdem sollten Sie wissen, was Ihre HTTP-Bibliothek zur Verfügung stellt.

Verbindungsprotokolle (HTTP/*) verwenden

In diesem Abschnitt werden die unterstützten Verbindungsprotokolle – in der Regel eine HTTP-Version – erläutert, die Cloud APIs für die Kommunikation zwischen Clients und Servern verwenden können. Außerdem erhalten Sie Empfehlungen hinsichtlich ihrer Verwendung. Im folgenden Abschnitt gehen wir im Detail auf den Aufbau von Anfragen und Antworten ein.

HTTP-Semantik

Halten Sie sich bei der Entwicklung von API-Clientcode an die standardmäßige HTTP-Protokollsemantik. 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 zählen HTTP/1.0, HTTP/1.1, SPDY/*, HTTP/2 und QUIC.

Einige API-Funktionen, wie Server-Push und Prioritäten, werden möglicherweise nur von neueren HTTP-Protokollversionen unterstützt. Manche werden nur mit HTTP/2 vollständig angegeben, wie etwa Vollduplex-Streaming. Beachten Sie die Einschränkungen verschiedener HTTP-Versionen, wenn Sie eine dieser Funktionen im Rahmen der API-Spezifikation benötigen.

Generell empfehlen wir aufgrund der erhöhten Leistung sowie der Robustheit gegenüber Netzwerkausfällen HTTP/2.

Kanäle

Kanäle beziehen sich auf die L4-Netzwerkverbindungen (TCP- oder UDP-Sockets). Clientanwendungen sollten keine Annahmen darüber treffen, wie Kanäle zur Laufzeit verwendet werden, um HTTP-Anfragen zu senden. Kanäle werden für den Serverprozess in den meisten Fällen durch Proxys terminiert.

Verwenden Sie TCP-Verbindungen für HTTP/1.1-Clients immer wieder (Keep-Alive-Verbindung). Auch in der HTTP-Clientbibliothek wird zur Steigerung der Leistung vermutlich ein Verbindungspool verwaltet. Senden Sie Anfragen nicht über dieselbe TCP-Verbindung. Weitere Informationen finden Sie unter HTTP und TCP.

Alle modernen Browser unterstützen SPDY/*, HTTP/2 oder QUIC, womit gleichzeitig mehrere Anfragen über einen einzelnen Kanal übertragen werden können. Das herkömmliche Verbindungslimit (2–10) sollte kein Problem darstellen, es sei denn, die Anzahl der gleichzeitigen HTTP-Anfragen von einem einzelnen Client wird durch die Serverimplementierung auf beispielsweise 100 HTTP/2-Streams pro Ursprung gedrosselt.

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

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 meist zwischen 2.000 und 8.000 Zeichen liegt. Von manchen Browsern und Proxys wird sie erzwungen. Wenn die API GET-Anfragen mit URLs verwendet, die die Längenbeschränkung überschreiten, können solche Anfragen von Browsern abgelehnt werden. 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. Ausführliche Informationen erhalten Sie unter der Spezifikation für das Hypertext Transfer Protocol und mit der RFC für die Methode PATCH.

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 sollte DELETE 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-Wert ist application/x-www-form-urlencoded.

Streaming

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. Derzeit unterstützen Browser nur das 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" 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.