it-swarm.com.de

Wie kann ich mit Längenbeschränkungen für HTTP-GET-Abfragezeichenfolgen umgehen und trotzdem RESTful sein?

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

Heute stehe ich vor diesem Problem mit einem Suchformular. Wir haben ein Suchformular mit vielen Feldern entwickelt. Dieses Formular wird als GET-Anfrage an den Server gesendet, sodass 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 es keine Einschränkungen gibt.

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

Aber gibt es einen Fehler in der Gestaltung von REST-Diensten? Wenn wir eine begrenzte Länge in der GET-Anfrage haben, wie kann ich große Objekte an einen RESTful-Webservice senden? Zum Beispiel, wenn ich ein Programm habe, das Berechnungen basierend auf einer Datei vornimmt, und ich möchte einen RESTful-Webservice wie folgt bereitstellen: http://compute.com?content=<base64 file>. Dies funktioniert nicht, da die Abfragezeichenfolge keine unbegrenzte Länge hat.

Ich bin ein bisschen verwirrt ...

72
cbliard

Basierend auf Ihrer Beschreibung sollten Sie IMHO einen POST verwenden. POST dient zum Ablegen von Daten auf dem Server und erhält in einigen Fällen eine Antwort. In Ihrem Fall führen Sie eine Suche aus (senden Sie eine Abfrage an den Server) und erhalten Sie das Ergebnis dieser Suche (rufen Sie das Abfrageergebnis ab).

Die Definition von GET besagt, dass eine bereits vorhandene Ressource abgerufen werden muss. Per Definition wird mit POST eine neue Ressource erstellt. 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 vorher gesagt hat, könnten Sie dies mit einem POST tun (das Abfrageergebnis erstellen und speichern) und dann mit einem GET die Abfrage abrufen. Es ist jedoch praktischer, nur einen POST auszuführen und das Ergebnis abzurufen .

Hoffe das hilft! :)

50
jmpcm

Die HTTP-Spezifikation rät tatsächlich empfiehlt, POST zu verwenden, wenn Daten zur Berechnung an eine Ressource gesendet werden.

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

Sie können dann nach einiger Zeit die Suchmarken 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 Suchergebnisse weiterhin zwischenspeichern, Sie senden jedoch Ihre Abfrageparameter mit POST.

EDIT 

Zur Verdeutlichung stellt 01543164876 hier eine eindeutige ID für die Ressource dar, 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 Anfrage generiert wird. Dies würde bedeuten, dass Ihr Server "Suchobjekte" durchläuft und Sie diese regelmäßig mit einer Caching-Strategie reinigen 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 Wiederherstellen einer Suche eine vorhandene ID zurückgegeben wird, die möglicherweise bereits zwischengespeichert wurde.

56
Vincent Robert

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

Wenn Sie nun einen Browser verwenden möchten, um Ihre RESTful-Benutzeroberfläche anzuzeigen (alias während der Entwicklung/des Debugging), dann werden Sie dieses Limit einhalten. 

5
ken kranz

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üssen/müssen und dann die Abfrage POST in Betracht ziehen, wird diese Abfrage mit einer Abfrage-ID auf dem Server gespeichert und fordert die Abfrage später mit GET an von id.

5
PeterMmm

In Bezug auf Ihr Beispiel: http://compute.com?content={base64file} würde ich POST verwenden, da Sie "etwas" hochladen, das berechnet werden soll. Für mich ist dieses "Etwas" eher eine Ressource als ein einfacher Parameter. 

Im Gegensatz dazu würde ich bei der üblichen Suche anfangen, bei GET und Parametern zu bleiben. Sie machen es für api-clients so viel einfacher, mit Ihrem api zu testen. Machen Sie den schreibgeschützten Zugriff (der in den meisten Fällen den Groß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 sein, solange Sie dieses Limit nicht erreichen, gehen Sie zu GET und URL-Params. Dies funktioniert in 98% der Suchfälle. Handle nur, wenn du dieses Limit erreicht hast und dann auch POST mit der Payload (mit dem Mime-Typ Content-Type: application/x-www-form-urlencoded) einführen.

Hast du mehr Beispiele aus der realen Welt?

3
manuel aldana

5 Jahre später scheint es eine andere praktikable Option zu geben - verwenden Sie den Nachrichtentext von GET. Ich füge diese Antwort als Alternative zu allen oben genannten Vorschlägen bei, obwohl sie ihre eigenen Einschränkungen hat (einige Nachforschungen anstellen). 

0
G. Stoynev

Das ist leicht. Verwenden Sie POST. HTTP schreibt der URL-Länge für GET keine Beschränkung vor, Server jedoch nicht. Seien Sie pragmatisch und arbeiten Sie mit einem POST um das Problem. 

Sie können auch einen GET-Body verwenden (der zulässig ist), aber das ist ein doppelter Fehler, da er nicht korrekt verwendet wird und wahrscheinlich Serverprobleme hat. 

0
Rick O'Shea