Wie kann ich mit Einschränkungen der Länge von HTTP-GET-Abfragezeichenfolgen umgehen und trotzdem RESTful sein?

84

Wie unter http://www.boutell.com/newfaq/misc/urllength.html angegeben , ist die Länge der HTTP-Abfragezeichenfolge begrenzt. Sie kann durch den Client (Firefox, IE, ...), den Server (Apache, IIS, ...) oder die Netzwerkausrüstung (anwendbare Firewall, ...) eingeschränkt werden.

Heute begegne ich diesem Problem mit einem Suchformular. Wir haben ein Suchformular mit vielen Feldern entwickelt. Dieses Formular wird als GET-Anforderung an den Server gesendet, damit ich die resultierende Seite mit einem Lesezeichen versehen kann.

Wir haben so viele Felder, dass unsere Abfragezeichenfolge 1100 Byte lang ist, und wir haben eine Firewall, die HTTP-GET-Anforderungen mit mehr als 1024 Byte löscht. Unser Systemadministrator empfiehlt, stattdessen POST zu verwenden, damit keine Einschränkungen bestehen.

Sicher, POST wird funktionieren, aber ich fühle eine Suche wirklich als GET und nicht als POST. Daher werde ich unsere Feldnamen überprüfen, um sicherzustellen, dass die Abfragezeichenfolge nicht zu lang ist. Wenn ich nicht kann, bin ich pragmatisch und verwende POST.

Aber gibt es einen Fehler im Design von RESTful-Diensten? Wie kann ich große Objekte an einen RESTful-Webservice senden, wenn die Länge der GET-Anforderung begrenzt ist? Wenn ich beispielsweise ein Programm habe, das Berechnungen basierend auf einer Datei durchführt, und einen RESTful-Webservice wie diesen bereitstellen möchte : http://compute.com?content=<base64 file>. Dies funktioniert nicht, da die Abfragezeichenfolge nicht unbegrenzt lang ist.

Ich bin ein wenig verwirrt ...

cbliard
quelle
2
Was bedeutet erholsam in Bezug auf Ihren Kontext? Oder umschrieben: Warum ist GET erholsam und POST nicht? Weil GET mit einfacher String-Verkettung erstellt werden kann? Die Begrenzung der Abfragelänge dient dazu, eine dynamische Speicherzuweisung in Apps zu vermeiden, die schnell arbeiten sollen.
Khachik
5
Wenn ich eine Suche durchführen möchte, möchte ich nichts erstellen, löschen oder aktualisieren, sondern nur Daten abrufen. Daher sollte ich POST, DELETE oder PUT nicht verwenden und GET verwenden. So habe ich REST verstanden, aber ich kann mich irren
cbliard
GET ist nicht für die Suche geeignet, da sich die Ergebnisse einer Suche im Laufe der Zeit ändern können. Die Webinfrastruktur ermöglicht häufig das Zwischenspeichern von GET-Anforderungen. Wenn Sie GET verwenden, besteht die Gefahr, dass Sie alte veraltete Ergebnisse für Suchvorgänge erhalten. POST ist der Weg, wie unten empfohlen.
Occulus
15
Alles ändert sich im Laufe der Zeit ( en.wikipedia.org/wiki/Impermanence ), so ist die Natur des Universums ... Aber GET sollte für die Suche verwendet werden, da die "Suchaktion" die Ergebnisse nicht ändert
Luxspes

Antworten:

51

Basierend auf Ihrer Beschreibung sollten Sie meiner Meinung nach einen POST verwenden. POST dient dazu, Daten auf den Server zu stellen und in einigen Fällen eine Antwort zu erhalten. In Ihrem Fall führen Sie eine Suche durch (senden Sie eine Abfrage an den Server) und erhalten das Ergebnis dieser Suche (rufen Sie das Abfrageergebnis ab).

Die Definition von GET besagt, dass es verwendet werden muss, um eine bereits vorhandene Ressource abzurufen. Per Definition soll POST eine neue Ressource erstellen. Genau das tun Sie: Erstellen Sie eine Ressource auf dem Server und rufen Sie sie ab! Auch wenn Sie das Suchergebnis nicht speichern, haben Sie ein Objekt auf dem Server erstellt und abgerufen. Wie PeterMmm zuvor sagte, können Sie dies mit einem POST tun (das Abfrageergebnis erstellen und speichern) und dann ein GET verwenden, um die Abfrage abzurufen. Es ist jedoch praktischer, nur einen POST durchzuführen und das Ergebnis abzurufen.

Hoffe das hilft! :) :)

jmpcm
quelle
2
Sie haben Recht, ich kann es als POST sehen, da die Suche eine flüchtige neu berechnete Ressource ist. Aber ich habe immer noch Probleme, die Grenze zwischen POST und GET zu erkennen. Wenn ich alle Science-Fiction-Bücher in einer Bibliothek durchsuchen möchte, erhalte ich eine Sammlung vorhandener Ressourcen. Daher bin ich versucht, ein GET zu verwenden. Sie schlagen jedoch vor, es als POST zu betrachten, da die Suche selbst eine neue Ressource ist. Daher sollte die Abfragezeichenfolge in GET nur zum Ändern der Datendarstellung verwendet werden, nicht jedoch zum Filtern von Daten. Habe ich recht?
Cbliard
8
POST sollte nicht für Suchvorgänge verwendet werden. GET sollte verwendet werden. Auf diese Weise können Sie die resultierende URL und die Ergebnisse
freigeben
37
Diese Antwort klingt eher nach dem Versuch, mit Worten zu spielen. Durch diese Logik können wir alles als POST-Anforderungen erstellen und trotzdem RESTful sein.
Supertonsky
9
Diese Antwort scheint, als würde ein Anwalt mit mir sprechen :-) Die Frage lautet wirklich "Ich habe einen GET-Fall, okay. Aber meine Abfragezeichenfolge überschreitet die zulässige Länge. Wie gehe ich damit um?". Diese Antwort ablehnen.
G. Stoynev
2
Wenn diese Logik befolgt wird, erstellt jede Anforderung eine Ressource und ruft sie ab.
Alex
66

In der HTTP-Spezifikation wird empfohlen, POST zu verwenden, wenn Daten zur Berechnung an eine Ressource gesendet werden.

Ihre Suche sieht aus wie eine Berechnung, nicht wie eine Ressource. Wenn Sie weiterhin möchten, dass Ihre Suchergebnisse eine Ressource sind, können Sie ein Token erstellen, um dieses bestimmte Suchergebnis zu identifizieren und den Benutzeragenten zu dieser Ressource umzuleiten.

Sie können dann nach einiger Zeit Suchergebnis-Token löschen.

Beispiel

POST /search
query=something&category=c1&category=c2&...

201 Created
Location: /search/01543164876

dann

GET /search/01543164876

200 Ok
... your results here...

Auf diese Weise können Browser und Proxys weiterhin Suchergebnisse zwischenspeichern, aber Sie senden Ihre Abfrageparameter mithilfe von POST.

BEARBEITEN

Zur Verdeutlichung wird 01543164876hier eine eindeutige ID für die Ressource angegeben, die Ihre Suche darstellt. Diese beiden Anforderungen bedeuten im Wesentlichen: Erstellen Sie ein neues Suchobjekt mit diesen Kriterien und rufen Sie dann die Ergebnisse ab, die dem erstellten Suchobjekt zugeordnet sind.

Diese ID kann eine eindeutige ID sein, die für jede neue Anforderung generiert wird. Dies würde bedeuten, dass Ihr Server "Such" -Objekte verliert und Sie diese regelmäßig mit einer Caching-Strategie bereinigen müssen.

Oder es kann ein Hash aller Suchkriterien sein, die tatsächlich die vom Benutzer angeforderte Suche darstellen. Auf diese Weise können Sie IDs wiederverwenden, da beim erneuten Erstellen einer Suche eine vorhandene ID zurückgegeben wird, die möglicherweise bereits zwischengespeichert ist (oder nicht).

Vincent Robert
quelle
Wie wird die OP-Anforderung zum Lesezeichen der Abfrage erfüllt?
Rhabarber
2
@Rhubarb spricht es klar an, indem es eine Ressource für eine bestimmte Suche erstellt.
maulik13
3
Dies verlangsamt die Ergebnisse. Führen Sie einen Beitrag und dann ein GET durch. Es werden mindestens 300 ms mehr hinzugefügt, um die Suche abzurufen.
Jaxxbo
Link zur Quelle ist tot
Emobe
Ich bin verwirrt, was macht der Server zwischen dem POST und dem GET? Zwischenspeichert es die Suchdaten auf dem Server und wartet nur darauf, dass die GET-Anforderung eingeht? Dazu müsste eine eindeutige ID verwendet werden, damit Sie den Cache abrufen können. Ihre Antwort ist nett, aber sicherlich nicht vollständig. Und die Verwendung eines Caches würde die Dinge weniger zustandslos machen.
Alexander Mills
5

REST ist eine Art, Dinge zu tun, kein Protokoll. Selbst wenn Sie POST nicht mögen, wenn es wirklich ein GET ist, wird es funktionieren.

Wenn Sie bei der "Standard" -Definition von GET, POST usw. bleiben möchten / müssen, um eine Abfrage zu POSTEN, wird diese Abfrage auf dem Server mit einer Abfrage-ID gespeichert und fordert die Abfrage später mit GET nach ID an.

PeterMmm
quelle
4

In Bezug auf Ihr Beispiel: http://compute.com?content={base64file}Ich würde POST verwenden, weil Sie "etwas" hochladen, das berechnet werden soll. Für mich fühlt sich dieses "Etwas" eher wie eine Ressource als einfacher Parameter an.

Im Gegensatz dazu würde ich bei der üblichen Suche anfangen, mich an GET und Parameter zu halten. Sie machen es API-Clients so viel einfacher, Ihre API zu testen und damit herumzuspielen. Machen Sie den schreibgeschützten Zugriff (der in den meisten Fällen den größten Teil des Datenverkehrs ausmacht) so einfach wie möglich!

Das Dilemma großer Abfragezeichenfolgen ist jedoch eine gültige Einschränkung von GET. Hier würde ich pragmatisch vorgehen, solange Sie dieses Limit nicht erreichen, gehen Sie mit GET und URL-Parametern. Dies funktioniert in 98% der Suchfälle. Handeln Sie nur, wenn Sie dieses Limit erreicht haben, und führen Sie dann auch POST mit Nutzlast (mit MIME-Typ Content-Type: application/x-www-form-urlencoded) ein.

Haben Sie mehr Beispiele aus der Praxis?

Manuel Aldana
quelle
Die Berechnung war ein Beispiel aus der Praxis. Über die Suche möchten wir in der Lage sein, nach Transaktionen an mehreren Verkaufsstellen zu suchen. Daher öffnen wir ein neues Browserfenster, um die Verkaufsstellen auszuwählen. Und wenn wir validieren, ändern wir einen versteckten Parameter im Suchformular, um die ausgewählten Verkaufspunkte festzulegen. Wenn es wirklich viele davon gibt, hat die resultierende Suchanforderung eine sehr lange Abfragezeichenfolge.
Cbliard
4

Die Verwirrung um GET ist eine Einschränkung des Browsers. Wenn Sie eine RESTful-Schnittstelle für eine A2A- oder P2P-Anwendung erstellen, gibt es keine Beschränkung für die Länge Ihres GET.

Wenn Sie nun einen Browser zum Anzeigen Ihrer RESTful-Oberfläche verwenden möchten (auch bekannt als während der Entwicklung / des Debuggens), stoßen Sie auf diese Grenze, aber es gibt Tools, mit denen Sie dies umgehen können.

Ken Kranz
quelle
6
"GET ist eine Browser-Einschränkung" - es ist auch eine Server-Einschränkung. Sie werden feststellen, dass alle Webserver ein Limit erzwingen. Wenn Sie über CDNs verfügen, können diese auch ein Limit erzwingen. Durch die Verwendung anderer Tools zum Ausführen der Anforderung werden die Serverlimits nicht umgangen.
Courtney Miles
0

Dies ist einfach. Verwenden Sie POST. HTTP begrenzt die URL-Länge für GET nicht, Server jedoch. Seien Sie pragmatisch und umgehen Sie das mit einem POST.

Sie könnten auch einen GET-Body verwenden (der zulässig ist), aber das ist insofern ein Doppelschlag, als er nicht korrekt verwendet wird und wahrscheinlich Serverprobleme haben wird.

Rick O'Shea
quelle