2010-11-17 5 views
65

Wie in http://www.boutell.com/newfaq/misc/urllength.html angegeben, ist die Länge der HTTP-Abfragezeichenfolge begrenzt. Es kann durch den Client (Firefox, IE, ...), den Server (Apache, IIS, ...) oder die Netzwerkausrüstung (anwendbare Firewall, ...) begrenzt werden.Wie kann ich mit HTTP GET Abfragezeichenfolgenlängenbeschränkungen umgehen und möchte trotzdem RESTful sein?

Heute stelle ich dieses Problem mit einem Suchformular. Wir haben ein Suchformular mit vielen Feldern entwickelt, und dieses Formular wird als GET-Anfrage an den Server gesendet, damit ich die resultierende Seite als Lesezeichen speichern kann.

Wir haben so viele Felder, dass unsere Abfragezeichenfolge 1100 Bytes lang ist, und wir haben eine Firewall, die HTTP GET-Anfragen mit mehr als 1024 Bytes löscht. Unser Systemadministrator empfiehlt uns, stattdessen POST zu verwenden, damit es keine Beschränkung gibt.

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

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

Ich bin ein wenig verwirrt ...

+2

Was bedeutet erholsam in Bezug auf Ihren Kontext? Oder paraphrasieren: warum GET ist erholsam und POST ist nicht? Weil GET mit einfachen String-Verkettungen konstruiert werden kann? Die Abfragelängenbegrenzung dient dazu, die dynamische Speicherzuweisung in Apps zu vermeiden, die schnell arbeiten sollen. – khachik

+4

Wenn ich eine Suche durchführen möchte, möchte ich nichts erstellen, löschen oder aktualisieren, ich möchte nur Daten abrufen, also sollte ich nicht POST, DELETE oder PUT verwenden, und ich sollte GET verwenden.So habe ich REST verstanden, aber ich könnte mich irren – cbliard

+0

GET ist nicht geeignet für die Suche, weil sich die Ergebnisse einer Suche im Laufe der Zeit ändern können. Die Web-Infrastruktur ermöglicht häufig das Zwischenspeichern von GET-Anforderungen. Wenn Sie GET verwenden, riskieren Sie alte veraltete Ergebnisse für Suchen. POST ist der Weg, wie unten empfohlen. – occulus

Antwort

45

Basierend auf Ihrer Beschreibung, IMHO sollten Sie 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 (Abfrageergebnis abrufen).

Die Definition von GET besagt, dass sie zum Abrufen einer bereits vorhandenen Ressource verwendet werden muss. Per Definition soll POST eine neue Ressource erstellen. Genau das machen Sie: Erstellen Sie eine Ressource auf dem Server und laden Sie sie ab! Auch wenn Sie das Suchergebnis nicht speichern, haben Sie ein Objekt auf dem Server erstellt und es abgerufen. Wie PeterMmm vorhin gesagt hat, könnten Sie dies mit einem POST tun (das Abfrageergebnis erzeugen und speichern) und dann ein GET verwenden, um die Abfrage zu reaktivieren, aber es ist praktischer, nur einen POST durchzuführen und das Ergebnis abzurufen.

Hoffe, das hilft! :)

+2

Sie haben Recht, ich kann es als POST sehen, weil Die Suche ist eine flüchtige neu berechnete Ressource. Aber ich habe immer noch Probleme, die Grenze zwischen POST und GET zu sehen. Wenn ich alle Science-Fiction-Bücher in einer Bibliothek durchsuchen will, werde ich eine Sammlung von vorhandenen Ressourcen bekommen, also bin ich versucht, ein GET zu verwenden, aber Sie schlagen vor, es als POST zu sehen, weil 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

+0

Ja, wenn Sie aus der Perspektive der Suche schauen, ist sie eine Ressource selbst, die Sie erstellen müssen (machen Sie einen POST), um einige Daten (ein GET) abzurufen. Sie können eine Suche als neues Objekt sehen, das aus einer Sammlung bereits vorhandener Objekte instanziiert wurde! Im Beispiel der Bibliothek haben Sie die Bücher (Ressourcen) in den Regalen, aber Sie wollen nur einen Teil von ihnen und dieser Teil kann als neue Ressource angesehen werden (denken Sie an ein neues Regal nur mit den Büchern, die Sie suchen). – jmpcm

+0

@jmpcm Um es klar zu sagen, Sie sagen, dass alle GET-Parameter, die einfach angeben, welche genaue Ressource zu bekommen (dh '/? File = 123.txt') sind die einzigen Möglichkeiten, GET zu verwenden, und dass POST sein sollte benutzt für alles Suchende (dh '/? file = *. txt'), oder bin ich falsch verstanden? – Patrick

5

REST eine Art und Weise, die 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, oder vielleicht eine POST-Abfrage in Erwägung ziehen, wird diese Abfrage auf dem Server mit einer Abfrage-ID gespeichert und die Abfrage später mit GET angefordert nach ID.

47

HTTP-Spezifikation tatsächlich advises to use POST when sending data to a resource für die Berechnung.

Ihre Suche sieht wie eine Berechnung aus, nicht eine Ressource selbst. Was Sie tun könnten, wenn Sie weiterhin möchten, dass Ihre Suchergebnisse eine Ressource sind, erstellen Sie ein Token, um dieses spezifische Suchergebnis zu identifizieren und den Benutzeragenten auf diese Ressource umzuleiten.

Sie können dann Suchergebnisse nach einiger Zeit 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, Browser und Proxies können immer noch Ergebnisse Cache suchen, aber Sie sind die Übermittlung Ihrer Abfrageparameter POST.

EDIT

Zur Verdeutlichung stellt 01543164876 hier eine eindeutige ID für die Ressource Ihre Suche darstellt. Diese zwei Anfragen 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 "Such" -Objekte durchläuft und Sie diese regelmäßig mit einer Cache-Strategie bereinigen müssen.

Oder es kann ein Hash aller Suchkriterien sein, die tatsächlich die vom Benutzer gestellte Suche darstellen. Auf diese Weise können Sie IDs erneut verwenden, da beim erneuten Erstellen einer Suche eine vorhandene ID zurückgegeben wird, die möglicherweise bereits zwischengespeichert wurde.

+0

How adressiert dies die OP-Anforderung, die Abfrage zu bookmarken? – Rhubarb

+2

@Rhubarb adressiert es eindeutig durch das Erstellen einer Ressource für eine bestimmte Suche. – maulik13

+2

Dies wird die Ergebnisse verlangsamen. Führen Sie einen Post aus und führen Sie dann einen GET aus. es wird mindestens 300ms mehr hinzufügen, um die Suche zu holen. – jaxxbo

3

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

Im Gegensatz dazu in der üblichen Suche würde ich anfangen, mit GET und Parametern zu bleiben. Sie machen es für api-Kunden so viel einfacher, mit Ihrer API zu experimentieren. Machen Sie den schreibgeschützten Zugriff (der in den meisten Fällen der Hauptteil des Datenverkehrs ist) so einfach wie möglich!

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

Haben Sie mehr Beispiele aus der Praxis?

+0

Die Berechnung war ein reales Beispiel. Über die Suche wollen wir nach Transaktionen auf mehreren Verkaufspunkten suchen können, also öffnen wir ein neues Browserfenster, um die Verkaufspunkte auszuwählen. Und wenn wir validieren, modifizieren wir einen versteckten Parameter im Suchformular, um die ausgewählten Verkaufspunkte festzulegen. Wenn es wirklich viele von ihnen gibt, hat die resultierende Suchanforderung eine sehr lange Abfragezeichenfolge. – cbliard

5

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

Jetzt, wenn Sie einen Browser verwenden möchten, um Ihre RESTful-Schnittstelle (aka während der Entwicklung/Debuggen) anzuzeigen, dann stoßen Sie auf dieses Limit, aber es gibt Tools da draußen, um dies zu umgehen.

0

5 Jahre später scheint es eine andere praktikable Option zu geben - benutzen Sie den Nachrichtentext GET. Ich füge diese Antwort als eine Alternative zu allen obigen Vorschlägen ein, obwohl sie ihre eigenen Einschränkungen hat (recherchieren).

+1

https://xhr.spec.whatwg.org/#the-send()-method - nach der letzten Spezifikation wird der an XHR übergebene Text "GET" ignoriert – Victor

+0

google zeigt das als Fehler in Ihrer Domain an, mach es nicht –

0

Dies ist ein einfacher. Verwenden Sie POST. HTTP legt keine Begrenzung für die URL-Länge für GET fest, aber Server tun dies. Sei pragmatisch und arbeite das mit einem POST ab.

Sie könnten auch einen GET-Body (das ist erlaubt) verwenden, aber das ist ein Doppel-Whammy in, dass es nicht korrekte Verwendung ist und wahrscheinlich Serverprobleme haben wird.

Verwandte Themen