Zum Hauptinhalt springen

2. Architektur

HTTP wurde für die Architektur des World Wide Web (WWW) geschaffen und hat sich im Laufe der Zeit weiterentwickelt, um die Skalierbarkeitsanforderungen eines weltweiten Hypertext-Systems zu erfüllen. Ein Großteil dieser Architektur spiegelt sich in der Terminologie und den Syntaxproduktionen wider, die zur Definition von HTTP verwendet werden.

2.1. Client/Server-Nachrichtenübermittlung​

HTTP ist ein zustandsloses Anfrage/Antwort-Protokoll, das durch den Austausch von Nachrichten (Abschnitt 3) über eine zuverlässige "Verbindung" (Abschnitt 6) auf Transport- oder Sitzungsschicht arbeitet. Ein HTTP-"Client" ist ein Programm, das eine Verbindung zu einem Server aufbaut, um eine oder mehrere HTTP-Anfragen zu senden. Ein HTTP-"Server" ist ein Programm, das Verbindungen annimmt, um HTTP-Anfragen zu bedienen, indem es HTTP-Antworten sendet.

Die Begriffe "Client" und "Server" beziehen sich nur auf die Rollen, die diese Programme für eine bestimmte Verbindung übernehmen. Dasselbe Programm kann bei einigen Verbindungen als Client und bei anderen als Server agieren. Der Begriff "User Agent" bezeichnet eines der verschiedenen Client-Programme, die eine Anfrage initiieren, darunter (aber nicht beschränkt auf) Browser, Spider (webbasierte Roboter), Kommandozeilenwerkzeuge, benutzerdefinierte Anwendungen und mobile Apps. Der Begriff "Ursprungsserver" (origin server) bezeichnet das Programm, das maßgebliche Antworten für eine bestimmte Zielressource erzeugen kann. Die Begriffe "Absender" (sender) und "Empfänger" (recipient) bezeichnen jede Implementierung, die eine bestimmte Nachricht sendet bzw. empfängt.

HTTP stützt sich auf den Standard für Uniform Resource Identifier (URI) [RFC3986], um die Zielressource (Abschnitt 5.1) und Beziehungen zwischen Ressourcen anzugeben. Nachrichten werden in einem Format übertragen, das dem der Internet-Mail [RFC5322] und der Multipurpose Internet Mail Extensions (MIME) [RFC2045] ähnelt (zu den Unterschieden zwischen HTTP- und MIME-Nachrichten siehe Anhang A von [RFC7231]).

Der größte Teil der HTTP-Kommunikation besteht aus einer Abrufanfrage (GET) nach einer Repräsentation einer durch einen URI identifizierten Ressource. Im einfachsten Fall kann dies über eine einzelne bidirektionale Verbindung (===) zwischen dem User Agent (UA) und dem Ursprungsserver (O) erfolgen.

     request   >
UA ======================================= O
< response

Ein Client sendet eine HTTP-Anfrage in Form einer Anfragenachricht an einen Server; sie beginnt mit einer Anfragezeile, die eine Methode, einen URI und eine Protokollversion enthält (Abschnitt 3.1.1), gefolgt von Header-Feldern mit Anforderungsmodifizierern, Client-Informationen und Repräsentationsmetadaten (Abschnitt 3.2), einer Leerzeile zur Anzeige des Endes des Header-Abschnitts und schließlich einem Nachrichtenkörper, der den Payload-Body enthält (falls vorhanden, Abschnitt 3.3).

Ein Server antwortet auf die Anfrage eines Clients, indem er eine oder mehrere HTTP-Antwortnachrichten sendet; jede beginnt mit einer Statuszeile, die die Protokollversion, einen Erfolgs- oder Fehlercode und eine textuelle Grundphrase (reason phrase) enthält (Abschnitt 3.1.2), möglicherweise gefolgt von Header-Feldern mit Server-Informationen, Ressourcenmetadaten und Repräsentationsmetadaten (Abschnitt 3.2), einer Leerzeile zur Anzeige des Endes des Header-Abschnitts und schließlich einem Nachrichtenkörper, der den Payload-Body enthält (falls vorhanden, Abschnitt 3.3).

Eine Verbindung kann für mehrere Anfrage/Antwort-Austausche genutzt werden, wie in Abschnitt 6.3 definiert.

Das folgende Beispiel veranschaulicht einen typischen Nachrichtenaustausch für eine GET-Anfrage (Abschnitt 4.3.1 von [RFC7231]) auf den URI "http://www.example.com/hello.txt":

Client-Anfrage:

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

Server-Antwort:

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain

Hello World! My payload includes a trailing CRLF.

2.2. Implementierungsvielfalt​

Wenn man das Design von HTTP betrachtet, gerät man leicht in die Falle zu glauben, dass alle User Agents universelle Browser und alle Ursprungsserver große öffentliche Websites sind. In der Praxis ist das nicht der Fall. Gängige HTTP-User-Agents umfassen Haushaltsgeräte, Stereoanlagen, Waagen, Firmware-Aktualisierungsskripte, Kommandozeilenprogramme, mobile Apps und Kommunikationsgeräte in einer Vielzahl von Formen und Größen. Ebenso umfassen gängige HTTP-Ursprungsserver Heimautomatisierungseinheiten, konfigurierbare Netzwerkkomponenten, Büromaschinen, autonome Roboter, Nachrichten-Feeds, Verkehrskameras, Anzeigenauswahl und Video-Auslieferungsplattformen.

Der Begriff "User Agent" impliziert nicht, dass zum Zeitpunkt einer Anfrage ein menschlicher Nutzer direkt mit dem Software-Agenten interagiert. In vielen Fällen wird ein User Agent installiert oder konfiguriert, um im Hintergrund zu laufen und seine Ergebnisse zur späteren Prüfung zu speichern (oder nur eine Teilmenge derjenigen Ergebnisse zu speichern, die interessant oder fehlerhaft sein könnten). Spidern beispielsweise wird typischerweise ein Start-URI gegeben, und sie werden so konfiguriert, dass sie beim Durchsuchen des Web als Hypertext-Graph ein bestimmtes Verhalten befolgen.

Die Vielfalt der HTTP-Implementierungen bedeutet, dass nicht alle User Agents ihren Nutzern interaktive Vorschläge machen oder angemessene Warnungen zu Sicherheits- oder Datenschutzbedenken geben können. In den wenigen Fällen, in denen diese Spezifikation die Meldung von Fehlern an den Nutzer verlangt, ist es akzeptabel, wenn solche Meldungen nur in einer Fehlerkonsole oder Protokolldatei sichtbar sind. Ebenso können Anforderungen, dass eine automatisierte Aktion vor dem Fortfahren vom Nutzer bestätigt werden muss, durch vorab getroffene Konfigurationsentscheidungen, Laufzeitoptionen oder einfaches Vermeiden der unsicheren Aktion erfüllt werden; Bestätigung impliziert keine bestimmte Benutzeroberfläche und keine Unterbrechung der normalen Verarbeitung, wenn der Nutzer diese Wahl bereits getroffen hat.

2.3. Vermittler​

HTTP ermöglicht die Verwendung von Vermittlern, um Anfragen über eine Kette von Verbindungen zu erfüllen. Es gibt drei gängige Formen von HTTP-Vermittlern: Proxy, Gateway und Tunnel. In manchen Fällen kann ein einzelner Vermittler als Ursprungsserver, Proxy, Gateway oder Tunnel agieren und sein Verhalten je nach Art der einzelnen Anfrage wechseln.

     >             >             >             >
UA =========== A =========== B =========== C =========== O
< < < <

Die obige Abbildung zeigt drei Vermittler (A, B und C) zwischen User Agent und Ursprungsserver. Eine Anforderungs- oder Antwortnachricht, die die gesamte Kette durchläuft, passiert vier separate Verbindungen. Einige HTTP-Kommunikationsoptionen gelten möglicherweise nur für die Verbindung zum nächsten nicht als Tunnel fungierenden Nachbarn, nur für die Endpunkte der Kette oder für alle Verbindungen entlang der Kette. Obwohl das Diagramm linear ist, kann jeder Teilnehmer an mehreren gleichzeitigen Kommunikationen beteiligt sein. Beispielsweise kann B gleichzeitig Anfragen von vielen anderen Clients als A empfangen und/oder Anfragen an andere Server als C weiterleiten, während es A's Anfrage verarbeitet. Ebenso können spätere Anfragen über einen anderen Pfad von Verbindungen gesendet werden, häufig basierend auf dynamischer Konfiguration für die Lastverteilung.

Die Begriffe "upstream" und "downstream" werden verwendet, um Richtungsanforderungen in Bezug auf den Nachrichtenfluss zu beschreiben: Alle Nachrichten fließen von upstream nach downstream. Die Begriffe "inbound" und "outbound" werden verwendet, um Richtungsanforderungen in Bezug auf die Anforderungsroute zu beschreiben: "inbound" bedeutet zum Ursprungsserver hin und "outbound" bedeutet zum User Agent hin.

Ein "Proxy" ist ein Nachrichtenweiterleitungsagent (message-forwarding agent), der vom Client ausgewählt wird, üblicherweise über lokale Konfigurationsregeln, um Anfragen für bestimmte Arten absoluter URIs zu empfangen und zu versuchen, diese Anfragen durch Übersetzung über die HTTP-Schnittstelle zu erfüllen. Einige Übersetzungen sind minimal, etwa bei Proxy-Anfragen für "http"-URIs, während andere Anfragen eine Übersetzung zu und von gänzlich anderen Protokollen auf Anwendungsebene erfordern können. Proxys werden häufig eingesetzt, um die HTTP-Anfragen einer Organisation aus Gründen der Sicherheit, für Annotationsdienste oder für gemeinsames Caching über einen gemeinsamen Vermittler zu bündeln. Manche Proxys sind darauf ausgelegt, ausgewählte Nachrichten oder Payloads während der Weiterleitung zu transformieren, wie in Abschnitt 5.7.2 beschrieben.

Ein "Gateway" (auch "Reverse Proxy" genannt) ist ein Vermittler, der für die outbound-Verbindung als Ursprungsserver agiert, aber empfangene Anfragen übersetzt und sie inbound an einen anderen Server oder andere Server weiterleitet. Gateways werden häufig eingesetzt, um Alt- oder nicht vertrauenswürdige Informationsdienste zu kapseln, die Serverleistung durch "Accelerator"-Caching zu verbessern und die Partitionierung oder Lastverteilung von HTTP-Diensten auf mehrere Maschinen zu ermöglichen.

Alle HTTP-Anforderungen, die auf einen Ursprungsserver anwendbar sind, gelten auch für die outbound-Kommunikation eines Gateways. Ein Gateway kommuniziert mit inbound-Servern über ein beliebiges Protokoll, einschließlich privater Erweiterungen von HTTP, die außerhalb des Geltungsbereichs dieser Spezifikation liegen. Ein HTTP-zu-HTTP-Gateway, das mit HTTP-Servern von Drittanbietern interoperieren möchte, sollte jedoch die Anforderungen an User Agents für seine inbound-Verbindung erfüllen.

Ein "Tunnel" fungiert als blindes Relay zwischen zwei Verbindungen, ohne die Nachrichten zu verändern. Sobald er aktiv ist, gilt ein Tunnel nicht als Teilnehmer der HTTP-Kommunikation, obwohl er möglicherweise durch eine HTTP-Anfrage initiiert wurde. Ein Tunnel hört auf zu existieren, wenn beide Enden der weitergeleiteten Verbindung geschlossen werden. Tunnel werden verwendet, um eine virtuelle Verbindung durch einen Vermittler hindurch zu verlängern, etwa wenn Transport Layer Security (TLS, [RFC5246]) genutzt wird, um eine vertrauliche Kommunikation durch einen gemeinsam genutzten Firewall-Proxy aufzubauen.

Die obigen Kategorien für Vermittler betrachten nur solche, die als Teilnehmer an der HTTP-Kommunikation agieren. Es gibt auch Vermittler, die auf niedrigeren Schichten des Netzwerkprotokollstapels agieren und HTTP-Verkehr ohne Wissen oder Erlaubnis der Nachrichtenabsender filtern oder umleiten können. Netzwerkvermittler sind (auf Protokollebene) nicht von einem Man-in-the-Middle-Angriff zu unterscheiden und führen oft zu Sicherheitslücken oder Interoperabilitätsproblemen, weil sie versehentlich die HTTP-Semantik verletzen.

Ein "Interception Proxy" [RFC3040] (auch allgemein als "Transparent Proxy" [RFC1919] oder "Captive Portal" bekannt) unterscheidet sich beispielsweise von einem HTTP-Proxy, weil er nicht vom Client ausgewählt wird. Stattdessen filtert oder leitet ein Interception Proxy ausgehende TCP-Port-80-Pakete (und gelegentlich anderen gängigen Portverkehr) um. Interception Proxys finden sich häufig an öffentlichen Netzzugangspunkten, als Mittel zur Durchsetzung eines Kontoabonnements, bevor die Nutzung nicht-lokaler Internetdienste erlaubt wird, sowie in Unternehmens-Firewalls zur Durchsetzung von Netzwerknutzungsrichtlinien.

HTTP ist als zustandsloses Protokoll definiert, was bedeutet, dass jede Anforderungsnachricht isoliert verstanden werden kann. Viele Implementierungen hängen vom zustandslosen Design von HTTP ab, um Proxy-Verbindungen wiederzuverwenden oder Anfragen dynamisch über mehrere Server zu verteilen. Daher darf ein Server NICHT annehmen, dass zwei Anfragen über dieselbe Verbindung von demselben User Agent stammen, es sei denn, die Verbindung ist gesichert und spezifisch für diesen Agenten. Einige nicht standardisierte HTTP-Erweiterungen (z. B. [RFC4559]) sind dafür bekannt, diese Anforderung zu verletzen, was zu Sicherheits- und Interoperabilitätsproblemen führt.

2.4. Caches​

Ein "Cache" ist ein lokaler Speicher früherer Antwortnachrichten und das Subsystem, das deren Speicherung, Abruf und Löschung steuert. Ein Cache speichert cachefähige Antworten, um die Antwortzeit und den Bandbreitenverbrauch des Netzwerks bei zukünftigen gleichwertigen Anfragen zu reduzieren. Jeder Client oder Server KANN einen Cache einsetzen, obwohl ein Server einen Cache nicht nutzen kann, während er als Tunnel agiert.

Die Wirkung eines Caches besteht darin, dass die Anfrage/Antwort-Kette verkürzt wird, wenn einer der Teilnehmer entlang der Kette eine für diese Anfrage anwendbare zwischengespeicherte Antwort hat. Das Folgende veranschaulicht die resultierende Kette, wenn B eine zwischengespeicherte Kopie einer früheren Antwort von O (über C) für eine Anfrage hat, die von UA oder A nicht zwischengespeichert wurde.

     >             >
UA =========== A =========== B - - - - - - C - - - - - - O
< <

Eine Antwort ist "cachefähig", wenn ein Cache eine Kopie der Antwortnachricht speichern darf, um sie zur Beantwortung nachfolgender Anfragen zu verwenden. Selbst wenn eine Antwort cachefähig ist, können der Client oder der Ursprungsserver zusätzliche Einschränkungen dafür auferlegen, wann diese zwischengespeicherte Antwort für eine bestimmte Anfrage verwendet werden darf. HTTP-Anforderungen an das Cache-Verhalten und an cachefähige Antworten sind in Abschnitt 2 von [RFC7234] definiert.

Über das World Wide Web und innerhalb großer Organisationen ist eine breite Vielfalt an Architekturen und Konfigurationen von Caches im Einsatz. Dazu gehören nationale Hierarchien von Proxy-Caches zur Einsparung transozeanischer Bandbreite, kollaborative Systeme, die Cache-Einträge per Broadcast oder Multicast verbreiten, Archive vorab abgerufener Cache-Einträge für Offline- oder Umgebungen mit hoher Latenz und so weiter.

2.5. Konformität und Fehlerbehandlung​

Diese Spezifikation zielt auf Konformitätskriterien gemäß der Rolle eines Teilnehmers an der HTTP-Kommunikation ab. Daher werden HTTP-Anforderungen an Absender, Empfänger, Clients, Server, User Agents, Vermittler, Ursprungsserver, Proxys, Gateways oder Caches gestellt, je nachdem, welches Verhalten durch die Anforderung eingeschränkt wird. Zusätzliche (soziale) Anforderungen werden an Implementierungen, Ressourceneigentümer und Registrierungen von Protokollelementen gestellt, wenn sie über den Umfang einer einzelnen Kommunikation hinaus gelten.

Das Verb "generate" wird anstelle von "send" verwendet, wenn eine Anforderung zwischen dem Erzeugen eines Protokollelements und dem bloßen Weiterleiten eines empfangenen Elements stromabwärts unterscheidet.

Eine Implementierung gilt als konform, wenn sie alle Anforderungen erfüllt, die mit den Rollen verbunden sind, die sie in HTTP einnimmt.

Konformität umfasst sowohl die Syntax als auch die Semantik von Protokollelementen. Ein Absender darf KEINE Protokollelemente erzeugen, die eine Bedeutung vermitteln, von der dieser Absender weiß, dass sie falsch ist. Ein Absender darf KEINE Protokollelemente erzeugen, die nicht zur Grammatik der entsprechenden ABNF-Regeln passen. Innerhalb einer bestimmten Nachricht darf ein Absender KEINE Protokollelemente oder Syntaxalternativen erzeugen, die nur von Teilnehmern in anderen Rollen erzeugt werden dürfen (d. h. eine Rolle, die der Absender für diese Nachricht nicht hat).

Wenn ein empfangenes Protokollelement geparst wird, muss der Empfänger in der Lage sein, jeden Wert angemessener Länge zu parsen, der auf die Rolle des Empfängers anwendbar ist und zur Grammatik der entsprechenden ABNF-Regeln passt. Beachten Sie jedoch, dass einige empfangene Protokollelemente möglicherweise nicht geparst werden. Beispielsweise kann ein Vermittler, der eine Nachricht weiterleitet, ein Header-Feld in generische Komponenten field-name und field-value parsen, das Header-Feld dann aber weiterleiten, ohne den field-value weiter zu parsen.

HTTP hat für viele seiner Protokollelemente keine spezifischen Längenbeschränkungen, weil die möglicherweise angemessenen Längen je nach Bereitstellungskontext und Zweck der Implementierung stark variieren. Daher hängt die Interoperabilität zwischen Absendern und Empfängern von gemeinsamen Erwartungen darüber ab, was für jedes Protokollelement eine angemessene Länge ist. Darüber hinaus hat sich das, was gemeinhin als angemessene Länge für einige Protokollelemente verstanden wird, im Verlauf der letzten zwei Jahrzehnte der HTTP-Nutzung geändert und wird sich voraussichtlich auch in Zukunft weiter ändern.

Mindestens muss ein Empfänger in der Lage sein, Längen von Protokollelementen zu parsen und zu verarbeiten, die mindestens so groß sind wie die Werte, die er für dieselben Protokollelemente in anderen Nachrichten erzeugt. Beispielsweise muss ein Ursprungsserver, der sehr lange URI-Referenzen auf seine eigenen Ressourcen veröffentlicht, in der Lage sein, dieselben Referenzen zu parsen und zu verarbeiten, wenn sie als Anfrageziel empfangen werden.

Ein Empfänger muss ein empfangenes Protokollelement gemäß der Semantik interpretieren, die diese Spezifikation dafür definiert, einschließlich Erweiterungen dieser Spezifikation, es sei denn, der Empfänger hat (durch Erfahrung oder Konfiguration) festgestellt, dass der Absender das, was durch diese Semantik impliziert wird, fehlerhaft implementiert. Beispielsweise kann ein Ursprungsserver den Inhalt eines empfangenen Accept-Encoding-Header-Felds ignorieren, wenn die Prüfung des User-Agent-Header-Felds eine bestimmte Implementierungsversion anzeigt, die bekanntermaßen beim Empfang bestimmter Content Codings fehlschlägt.

Sofern nicht anders angegeben, kann ein Empfänger versuchen, ein nutzbares Protokollelement aus einem ungültigen Konstrukt wiederherzustellen. HTTP definiert keine spezifischen Fehlerbehandlungsmechanismen, außer wenn diese direkte Auswirkungen auf die Sicherheit haben, da verschiedene Anwendungen des Protokolls unterschiedliche Fehlerbehandlungsstrategien erfordern. Beispielsweise möchte ein Webbrowser möglicherweise transparent von einer Antwort wiederherstellen, bei der das Location-Header-Feld nicht gemäß der ABNF geparst werden kann, während ein Systemsteuerungs-Client jede Form der Fehlerbehebung als gefährlich ansehen könnte.

2.6. Protokollversionierung​

HTTP verwendet ein Nummerierungsschema ".", um Versionen des Protokolls anzugeben. Diese Spezifikation definiert Version "1.1". Die Protokollversion als Ganzes zeigt die Konformität des Absenders mit der Menge von Anforderungen an, die in der entsprechenden Spezifikation von HTTP für diese Version dargelegt sind.

Die Version einer HTTP-Nachricht wird durch ein HTTP-version-Feld in der ersten Zeile der Nachricht angegeben. HTTP-version ist case-sensitiv.

HTTP-version  = HTTP-name "/" DIGIT "." DIGIT
HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive

Die HTTP-Versionsnummer besteht aus zwei Dezimalziffern, die durch einen "." (Punkt oder Dezimalpunkt) getrennt sind. Die erste Ziffer ("Major-Version") zeigt die HTTP-Nachrichtensyntax an, während die zweite Ziffer ("Minor-Version") die höchste Minor-Version innerhalb dieser Major-Version anzeigt, mit der der Absender konform ist und die er für zukünftige Kommunikation verstehen kann. Die Minor-Version gibt die Kommunikationsfähigkeiten des Absenders an, selbst wenn der Absender nur eine abwärtskompatible Teilmenge des Protokolls verwendet, wodurch der Empfänger weiß, dass fortschrittlichere Funktionen in der Antwort (durch Server) oder in zukünftigen Anfragen (durch Clients) verwendet werden können.

Wenn eine HTTP/1.1-Nachricht an einen HTTP/1.0-Empfänger [RFC1945] oder einen Empfänger mit unbekannter Version gesendet wird, wird die HTTP/1.1-Nachricht so konstruiert, dass sie als gültige HTTP/1.0-Nachricht interpretiert werden kann, wenn alle neueren Funktionen ignoriert werden. Diese Spezifikation stellt Anforderungen an die Empfängerversion für einige neue Funktionen, sodass ein konformer Absender nur kompatible Funktionen verwendet, bis er durch Konfiguration oder den Empfang einer Nachricht festgestellt hat, dass der Empfänger HTTP/1.1 unterstützt.

Die Interpretation eines Header-Felds ändert sich nicht zwischen Minor-Versionen derselben Major-HTTP-Version, obwohl sich das Standardverhalten eines Empfängers beim Fehlen eines solchen Felds ändern kann. Sofern nicht anders angegeben, sind Header-Felder, die in HTTP/1.1 definiert sind, für alle Versionen von HTTP/1.x definiert. Insbesondere sollten die Header-Felder Host und Connection von allen HTTP/1.x-Implementierungen implementiert werden, unabhängig davon, ob sie Konformität mit HTTP/1.1 angeben.

Neue Header-Felder können eingeführt werden, ohne die Protokollversion zu ändern, wenn ihre definierte Semantik es zulässt, dass Empfänger, die sie nicht erkennen, sie sicher ignorieren. Die Erweiterbarkeit von Header-Feldern wird in Abschnitt 3.2.1 erörtert.

Vermittler, die HTTP-Nachrichten verarbeiten (d. h. alle Vermittler außer denen, die als Tunnel agieren), MÜSSEN ihre eigene HTTP-version in weitergeleiteten Nachrichten senden. Mit anderen Worten, es ist ihnen nicht erlaubt, die erste Zeile einer HTTP-Nachricht blind weiterzuleiten, ohne sicherzustellen, dass die Protokollversion in dieser Nachricht einer Version entspricht, mit der dieser Vermittler sowohl beim Empfangen als auch beim Senden von Nachrichten konform ist. Das Weiterleiten einer HTTP-Nachricht ohne Umschreiben der HTTP-version kann zu Kommunikationsfehlern führen, wenn downstream-Empfänger die Version des Nachrichtenabsenders verwenden, um zu bestimmen, welche Funktionen für die spätere Kommunikation mit diesem Absender sicher zu verwenden sind.

Ein Client SOLLTE eine Anforderungsversion senden, die gleich der höchsten Version ist, mit der der Client konform ist und deren Major-Version nicht höher ist als die höchste vom Server unterstützte Version, sofern diese bekannt ist. Ein Client darf KEINE Version senden, mit der er nicht konform ist.

Ein Client KANN eine niedrigere Anforderungsversion senden, wenn bekannt ist, dass der Server die HTTP-Spezifikation fehlerhaft implementiert, aber erst, nachdem der Client mindestens eine normale Anfrage versucht und anhand des Antwortstatuscodes oder der Header-Felder (z. B. Server) festgestellt hat, dass der Server höhere Anforderungsversionen unsachgemäß behandelt.

Ein Server SOLLTE eine Antwortversion senden, die gleich der höchsten Version ist, mit der der Server konform ist und die eine Major-Version kleiner oder gleich der in der Anfrage empfangenen hat. Ein Server darf KEINE Version senden, mit der er nicht konform ist. Ein Server kann eine 505-Antwort (HTTP Version Not Supported) senden, wenn er den Dienst für die Major-Protokollversion des Clients aus irgendeinem Grund verweigern möchte.

Ein Server KANN eine HTTP/1.0-Antwort auf eine Anfrage senden, wenn bekannt oder vermutet wird, dass der Client die HTTP-Spezifikation fehlerhaft implementiert und nicht in der Lage ist, Antworten späterer Versionen korrekt zu verarbeiten, etwa wenn ein Client die Versionsnummer nicht korrekt parst oder wenn bekannt ist, dass ein Vermittler die HTTP-version blind weiterleitet, selbst wenn er nicht mit der angegebenen Minor-Version des Protokolls konform ist. Solche Protokoll-Downgrades SOLLTEN NICHT durchgeführt werden, es sei denn, sie werden durch bestimmte Client-Attribute ausgelöst, etwa wenn eines oder mehrere der Anforderungs-Header-Felder (z. B. User-Agent) eindeutig mit den von einem bekanntermaßen fehlerhaften Client gesendeten Werten übereinstimmen.

Die Absicht des Versionierungsdesigns von HTTP ist, dass die Major-Nummer nur erhöht wird, wenn eine inkompatible Nachrichtensyntax eingeführt wird, und dass die Minor-Nummer nur erhöht wird, wenn Änderungen am Protokoll die Wirkung haben, die Nachrichtensemantik zu erweitern oder zusätzliche Fähigkeiten des Absenders zu implizieren. Die Minor-Version wurde jedoch nicht für die zwischen [RFC2068] und [RFC2616] eingeführten Änderungen erhöht, und diese Überarbeitung hat solche Änderungen am Protokoll gezielt vermieden.

Wenn eine HTTP-Nachricht mit einer Major-Versionsnummer empfangen wird, die der Empfänger implementiert, aber mit einer höheren Minor-Versionsnummer als der Empfänger implementiert, SOLLTE der Empfänger die Nachricht so verarbeiten, als wäre sie in der höchsten Minor-Version innerhalb dieser Major-Version, mit der der Empfänger konform ist. Ein Empfänger kann annehmen, dass eine Nachricht mit einer höheren Minor-Version, wenn sie an einen Empfänger gesendet wird, der die Unterstützung dieser höheren Version noch nicht angezeigt hat, ausreichend abwärtskompatibel ist, um von jeder Implementierung derselben Major-Version sicher verarbeitet zu werden.

2.7. Uniform Resource Identifiers​

Uniform Resource Identifiers (URIs) [RFC3986] werden in HTTP durchgängig als Mittel zur Identifizierung von Ressourcen verwendet (Abschnitt 2 von [RFC7231]). URI-Referenzen werden verwendet, um Anfragen zu adressieren, Weiterleitungen anzugeben und Beziehungen zu definieren.

Die Definitionen von "URI-reference", "absolute-URI", "relative-part", "scheme", "authority", "port", "host", "path-abempty", "segment", "query" und "fragment" sind aus der generischen URI-Syntax übernommen. Eine Regel "absolute-path" ist für Protokollelemente definiert, die eine nicht leere Pfadkomponente enthalten können. (Diese Regel unterscheidet sich geringfügig von der Regel path-abempty aus RFC 3986, die einen leeren Pfad in Referenzen zulässt, und von der Regel path-absolute, die Pfade, die mit "//" beginnen, nicht zulässt.) Eine Regel "partial-URI" ist für Protokollelemente definiert, die einen relativen URI, aber keine Fragmentkomponente enthalten können.

URI-reference = <URI-reference, see [RFC3986], Section 4.1>
absolute-URI = <absolute-URI, see [RFC3986], Section 4.3>
relative-part = <relative-part, see [RFC3986], Section 4.2>
scheme = <scheme, see [RFC3986], Section 3.1>
authority = <authority, see [RFC3986], Section 3.2>
uri-host = <host, see [RFC3986], Section 3.2.2>
port = <port, see [RFC3986], Section 3.2.3>
path-abempty = <path-abempty, see [RFC3986], Section 3.3>
segment = <segment, see [RFC3986], Section 3.3>
query = <query, see [RFC3986], Section 3.4>
fragment = <fragment, see [RFC3986], Section 3.5>

absolute-path = 1*( "/" segment )
partial-URI = relative-part [ "?" query ]

Jedes Protokollelement in HTTP, das eine URI-Referenz zulässt, gibt in seiner ABNF-Produktion an, ob das Element irgendeine Form der Referenz (URI-reference) zulässt, nur einen URI in absoluter Form (absolute-URI), nur die Pfad- und optionalen Query-Komponenten oder eine Kombination davon. Sofern nicht anders angegeben, werden URI-Referenzen relativ zum effektiven Anfrage-URI (Abschnitt 5.5) geparst.

2.7.1. http-URI-Schema​

Das "http"-URI-Schema wird hiermit definiert, um Bezeichner entsprechend ihrer Verbindung mit dem hierarchischen Namensraum zu vergeben, der von einem potenziellen HTTP-Ursprungsserver verwaltet wird, der auf einem bestimmten Port auf TCP-Verbindungen ([RFC0793]) wartet.

http-URI = "http:" "//" authority path-abempty [ "?" query ]
[ "#" fragment ]

Der Ursprungsserver für einen "http"-URI wird durch die Authority-Komponente identifiziert, die eine Host-Kennung und einen optionalen TCP-Port enthält ([RFC3986], Abschnitt 3.2.2). Die hierarchische Pfadkomponente und die optionale Query-Komponente dienen als Bezeichner für eine potenzielle Zielressource innerhalb des Namensraums dieses Ursprungsservers. Die optionale Fragmentkomponente ermöglicht die indirekte Identifizierung einer sekundären Ressource, unabhängig vom URI-Schema, wie in Abschnitt 3.5 von [RFC3986] definiert.

Ein Absender darf KEINEN "http"-URI mit leerer Host-Kennung erzeugen. Ein Empfänger, der eine solche URI-Referenz verarbeitet, muss sie als ungültig zurückweisen.

Wird die Host-Kennung als IP-Adresse angegeben, ist der Ursprungsserver der Listener (falls vorhanden) auf dem angegebenen TCP-Port an dieser IP-Adresse. Ist host ein registrierter Name, so ist der registrierte Name ein indirekter Bezeichner zur Verwendung mit einem Namensauflösungsdienst wie DNS, um eine Adresse für diesen Ursprungsserver zu finden. Ist die Port-Subkomponente leer oder nicht angegeben, ist TCP-Port 80 (der reservierte Port für WWW-Dienste) der Standard.

Beachten Sie, dass das Vorhandensein eines URI mit einer bestimmten Authority-Komponente nicht impliziert, dass immer ein HTTP-Server auf diesem Host und Port auf Verbindungen wartet. Jeder kann einen URI prägen. Was die Authority-Komponente bestimmt, ist, wer das Recht hat, maßgeblich auf Anfragen zu antworten, die auf die identifizierte Ressource abzielen. Die delegierte Natur registrierter Namen und IP-Adressen erzeugt einen föderierten Namensraum, basierend auf der Kontrolle über den angegebenen Host und Port, unabhängig davon, ob ein HTTP-Server vorhanden ist. Siehe Abschnitt 9.1 zu Sicherheitserwägungen im Zusammenhang mit der Etablierung von Authority.

Wird ein "http"-URI in einem Kontext verwendet, der den Zugriff auf die angegebene Ressource verlangt, kann ein Client den Zugriff versuchen, indem er den Host in eine IP-Adresse auflöst, eine TCP-Verbindung zu dieser Adresse auf dem angegebenen Port aufbaut und eine HTTP-Anfragenachricht (Abschnitt 3) mit den identifizierenden Daten des URI (Abschnitt 5) an den Server sendet. Antwortet der Server auf diese Anfrage mit einer nicht-vorläufigen HTTP-Antwortnachricht, wie in Abschnitt 6 von [RFC7231] beschrieben, so gilt diese Antwort als maßgebliche Antwort auf die Anfrage des Clients.

Obwohl HTTP unabhängig vom Transportprotokoll ist, ist das "http"-Schema spezifisch für TCP-basierte Dienste, weil der Namensdelegierungsprozess zur Etablierung von Authority auf TCP angewiesen ist. Ein HTTP-Dienst, der auf einem anderen zugrunde liegenden Verbindungsprotokoll basiert, würde vermutlich mit einem anderen URI-Schema identifiziert werden, so wie das "https"-Schema (unten) für Ressourcen verwendet wird, die eine Ende-zu-Ende-gesicherte Verbindung erfordern. Andere Protokolle könnten ebenfalls verwendet werden, um Zugang zu "http"-identifizierten Ressourcen zu bieten -- nur die maßgebliche Schnittstelle ist spezifisch für TCP.

Die generische URI-Syntax für Authority enthält außerdem eine veraltete userinfo-Subkomponente ([RFC3986], Abschnitt 3.2.1), um Benutzerauthentifizierungsinformationen in den URI aufzunehmen. Einige Implementierungen nutzen die userinfo-Komponente für die interne Konfiguration von Authentifizierungsinformationen, etwa innerhalb von Befehlsaufrufoptionen, Konfigurationsdateien oder Lesezeichenlisten, obwohl eine solche Nutzung eine Benutzerkennung oder ein Passwort offenlegen kann. Ein Absender darf die userinfo-Subkomponente (und ihr "@"-Trennzeichen) NICHT erzeugen, wenn eine "http"-URI-Referenz innerhalb einer Nachricht als Anfrageziel oder Header-Feldwert erzeugt wird. Bevor ein von einer nicht vertrauenswürdigen Quelle empfangener "http"-URI verwendet wird, SOLLTE ein Empfänger auf userinfo prüfen und dessen Vorhandensein als Fehler behandeln; es wird wahrscheinlich verwendet, um die Authority zum Zweck von Phishing-Angriffen zu verschleiern.

2.7.2. https-URI-Schema​

Das "https"-URI-Schema wird hiermit definiert, um Bezeichner entsprechend ihrer Verbindung mit dem hierarchischen Namensraum zu vergeben, der von einem potenziellen HTTP-Ursprungsserver verwaltet wird, der auf einem bestimmten TCP-Port auf TLS-gesicherte Verbindungen ([RFC5246]) wartet.

Alle oben für das "http"-Schema aufgeführten Anforderungen sind auch Anforderungen für das "https"-Schema, mit der Ausnahme, dass TCP-Port 443 der Standard ist, wenn die Port-Subkomponente leer oder nicht angegeben ist, und dass der User Agent sicherstellen muss, dass seine Verbindung zum Ursprungsserver durch die Verwendung starker Verschlüsselung, Ende-zu-Ende, gesichert ist, bevor er die erste HTTP-Anfrage sendet.

https-URI = "https:" "//" authority path-abempty [ "?" query ]
[ "#" fragment ]

Beachten Sie, dass das "https"-URI-Schema sowohl von TLS als auch von TCP abhängt, um Authority zu etablieren. Über das "https"-Schema verfügbar gemachte Ressourcen haben keine gemeinsame Identität mit dem "http"-Schema, selbst wenn ihre Ressourcenbezeichner dieselbe Authority angeben (denselben Host, der auf denselben TCP-Port wartet). Sie sind unterschiedliche Namensräume und gelten als unterschiedliche Ursprungsserver. Eine Erweiterung von HTTP, die definiert ist, um auf ganze Host-Domänen anzuwenden, wie das Cookie-Protokoll [RFC6265], kann jedoch zulassen, dass von einem Dienst gesetzte Informationen die Kommunikation mit anderen Diensten innerhalb einer übereinstimmenden Gruppe von Host-Domänen beeinflussen.

Der Prozess für den maßgeblichen Zugriff auf eine "https"-identifizierte Ressource ist in [RFC2818] definiert.

2.7.3. Normalisierung und Vergleich von http- und https-URIs​

Da die Schemata "http" und "https" der generischen URI-Syntax entsprechen, werden solche URIs gemäß dem in Abschnitt 6 von [RFC3986] definierten Algorithmus normalisiert und verglichen, wobei die oben für jedes Schema beschriebenen Standardwerte verwendet werden.

Ist der Port gleich dem Standardport für ein Schema, besteht die Normalform darin, die Port-Subkomponente wegzulassen. Wenn eine leere Pfadkomponente nicht in absoluter Form als Anfrageziel einer OPTIONS-Anfrage verwendet wird, ist sie einem absoluten Pfad "/" gleichwertig, sodass die Normalform darin besteht, stattdessen einen Pfad "/" anzugeben. Schema und Host sind case-insensitiv und werden normalerweise in Kleinbuchstaben angegeben; alle anderen Komponenten werden case-sensitiv verglichen. Zeichen, die nicht zur Menge der "reserved" gehören, sind ihren prozentkodierten Oktetten gleichwertig: Die Normalform besteht darin, sie nicht zu kodieren (siehe Abschnitte 2.1 und 2.2 von [RFC3986]).

Beispielsweise sind die folgenden drei URIs gleichwertig:

http://example.com:80/~smith/home.html
http://EXAMPLE.com/%7Esmith/home.html
http://EXAMPLE.com:/%7esmith/home.html