Ich entwickle gerade einen neuen RESTful Webservice für unsere Anwendung.
Bei einem GET auf bestimmte Entitäten können Clients den Inhalt der Entität anfordern. Wenn sie einige Parameter hinzufügen möchten (z. B. Sortieren einer Liste), können sie diese Parameter in den Abfrage-String einfügen.
Alternativ möchte ich, dass die Benutzer diese Parameter im Anfragetext angeben können. HTTP/1.1 scheint dies nicht ausdrücklich zu verbieten. Dadurch können sie mehr Informationen angeben, was die Angabe komplexer XML-Anfragen erleichtern könnte.
Meine Fragen:
- Ist das überhaupt eine gute Idee?
- Werden HTTP-Clients Probleme mit der Verwendung von Request Bodies innerhalb einer GET-Anfrage haben?
620 Stimmen
Der Vorteil besteht darin, dass XML- oder JSON-Anfragekörper problemlos gesendet werden können, es gibt keine Längenbeschränkung und sie sind einfacher zu kodieren (UTF-8).
39 Stimmen
Wenn Sie eine sichere und idempotente Methode suchen, die Anfragekörper erlaubt, sollten Sie sich SEARCH, PROPFIND und REPORT ansehen. Wenn Sie GET nicht verwenden und einen Anfragebody haben, wird das Caching natürlich mehr oder weniger zunichte gemacht.
3 Stimmen
Unabhängig davon, ob die Spezifikation dies zulässt, verstößt es gegen den Geist von REST.
3 Stimmen
Viel Glück mit Kunden, die Abfragemethoden wie SEARCH implementieren. Es ist viel wahrscheinlicher, dass Sie GET + Body verwenden können. Aber Fiddler für eine nicht zulassen, obwohl die meisten Browser wird (oder haben in der Vergangenheit)
310 Stimmen
@fijiaaron: Es ist 3 Jahre später, und seitdem habe ich umfangreiche Erfahrungen mit dem Schreiben von Webservices gesammelt. Das ist im Grunde alles, was ich in den letzten paar Jahren gemacht habe. Ich kann mit Sicherheit sagen, dass es in der Tat eine sehr schlechte Idee ist, einen Body zu einer GET-Anfrage hinzuzufügen. Die ersten beiden Antworten stehen wie ein Fels in der Brandung.
1 Stimmen
Ich bin einverstanden. Es ist machbar, wenn man alles vom Client bis zum Server kontrolliert (aber wozu braucht man dann einen Webservice). Aber wenn jemand das möchte, kann er es tun, und anstatt zu sagen, dass etwas nicht möglich ist, können wir die Fallstricke erklären. Ich bin auf ähnliche Probleme gestoßen, und die beste Lösung, die mir eingefallen ist, ist die Verwendung von POST, und sagen Sie es nur nicht Roy Fielding, denn das würde ihn zum Weinen bringen.
0 Stimmen
@fijiaaron: Ich kann nicht für ihn sprechen, aber ich würde bezweifeln, dass er glaubt, dass reines REST das A und O ist. Wählen Sie das richtige Werkzeug für die Aufgabe. Er scheint sich jedoch sehr darum zu kümmern, dass der Begriff REST falsch verwendet wird.
3 Stimmen
@Evert: Besteht die Möglichkeit, dass Sie einige Details zu den Herausforderungen mitteilen, die Sie mit GETs und dem Senden von Inhalten im Body hatten? Ich schreibe meine erste API und ich denke, ich werde dazu gebracht, einen GET + Body-Ansatz zu verwenden. Es wäre nützlich, einige Beispiele aus der Praxis zu haben, in denen Schwierigkeiten aufgetreten sind, und mögliche Lösungen.
40 Stimmen
@Ellesedil: Einfach ausgedrückt: Die Vorteile, die die Verwendung von GET gegenüber POST bietet, ergeben sich aus der Art und Weise, wie HTTP konzipiert ist. Diese Vorteile gibt es nicht mehr, wenn man den Standard auf diese Weise verletzt. Daher gibt es nur noch einen Grund, GET + einen Request Body anstelle von POST zu verwenden: Ästhetik. Opfern Sie ein robustes Design nicht der Ästhetik.
2 Stimmen
Diese Antwort fasst es gut zusammen, indem sie sich auf die HTTP/1.1-Spezifikation bezieht - stackoverflow.com/a/15656853/244128
23 Stimmen
Um zu unterstreichen, was Evert sagte: "Es gibt keine Längenbeschränkung". Wenn Ihr GET mit Abfrageparametern gegen die Längenbeschränkung (von 2048) verstößt, gibt es keine andere Möglichkeit, als die Abfrage-String-Informationen in ein json-Objekt zu packen, z. B. in den Body der Anfrage.
1 Stimmen
Chiming in, nachdem vor kurzem ein Native Http-Modul in C++ für IIS8 gebaut, kann ich sagen, dass OnReadEntity nicht auf Get-Anforderungen, nur auf Beiträge Feuer, oder ich hatte extreme Schwierigkeiten, um den Körper einer Get-Anforderung...
1 Stimmen
@Evert Was machen Sie also am Ende? JSON-Parameter als Base64 kodieren?
0 Stimmen
@JulianReschke Können Sie Verweise auf SEARCH usw. bereitstellen? Sie scheinen nicht Teil der HTTP-Anforderungsmethoden zu sein (zumindest auf Wikipedia).
1 Stimmen
@beldaz Wikipedia ist irrelevant; siehe iana.org/assignments/http-methods/http-methods.xhtml
4 Stimmen
Der OP hat später seine Gedanken in einem interessanten Artikel die auf genau diese Frage hinweist.
1 Stimmen
@beldaz SEARCH ist eine WebDAV-Methode. Siehe RFC5323: Web Distributed Authoring and Versioning (WebDAV) SEARCH
9 Stimmen
Mit dem Aufkommen von GDPR und der Frage, was in der URL-Abfrage offengelegt (und somit protokolliert) werden darf, mussten wir unsere APIs umschreiben, um sensible Informationen im Anforderungskörper zu übergeben und GETs in POSTs zu ändern. Also, zum Beispiel
GET http://host/customer?socialsecuritynumber={ssn}
wurdePOST http://host/customer/lookup
mit den sensiblen Informationen im Textkörper, die von der externen und internen Protokollierung ausgeschlossen sind0 Stimmen
Was wird empfohlen, wenn die Anfrage komplexe Daten enthält? Sollten Sie POST verwenden, um Daten anzufordern?
0 Stimmen
Kein Wort über die Sicherheitsaspekte der Url-Kodierung von GET-Anfragen... Ich kenne einige Beispiele, bei denen das Spielen mit dem Parameterstring in einer solchen GET-"Url" Hintertüren zu Daten öffnete, die nicht für die Öffentlichkeit bestimmt waren (der Computerclub CHAOS hat das vorgemacht). Abgesehen davon, dass es begrenzt, unhandlich und hässlich ist, ist es auch anfälliger für gelegentliche Hackerangriffe. Aus diesem Grund habe ich nie verstanden, warum die Welt die URL-Kodierung der Eingabe von Abfragedaten in den GET-Body vorzieht.
0 Stimmen
@BitTickler, denn es ist nicht üblich, sie in den Text zu setzen. Verwenden Sie POST, wenn Sie diese Anforderung haben.
0 Stimmen
@Evert Es sieht aus wie ein Hack und war wahrscheinlich ein Hack, der dann als Standard verkündet wurde.
0 Stimmen
@BitTickler Ganz im Gegenteil.
GET
hat eine starke semantische Bedeutung und ist keine "Leseoperation". Es war ein Standard, lange bevor Sie versucht haben, ihn zu missbrauchen =). Warum wollen Sie verwendenGET
?2 Stimmen
@Evert Tut mir leid, dass ich Ihre Ruhe störe. Ich glaube einfach nicht, dass Briefe, die Sie erhalten, die Nachricht auf den Umschlag hätten schreiben sollen. Und genau das macht die URL-Kodierung. Es ist ein Hack. Jemand wollte die URL-Zeichenfolge zwischenspeichern und als Schlüssel verwenden. Jemand wollte das Adressfeld auf dem Briefumschlag für die eigentliche Nachricht missbrauchen. Ein hässlicher Hack.
0 Stimmen
@BitTickler das ist ein guter Punkt, zeigt aber auch ein Missverständnis, wofür GET gedacht ist. Man schickt keinen Brief; es ist eher so, dass man dem Server sagt: 'Gib mir das Objekt mit diesem Namen'. Wenn Sie dies überladen, um einen generischen RPC-Aufruf zum Lesen zu meinen, dann dass ist wirklich der Hack. Sie verwenden ihn nicht wie vorgesehen.
0 Stimmen
@BitTickler, dass es echte Anwendungsfälle für eine sichere, idempotente HTTP-Anfrage gibt, die eine Vielzahl von Parametern enthält, und es wird daran gearbeitet, Methoden dafür zu definieren (
SEARCH
yQUERY
).0 Stimmen
Es ist so traurig, dass etwas, das vom ETag-Caching extrem profitieren würde, weil es wahrscheinlich dieselbe Antwort wie beim letzten Mal ist und weil es ein großer Antwortkörper ist, wie ein Bericht, etwas sein muss, das nicht gecached werden kann.
3 Stimmen
@doug65536 Eine Sache, die Sie heute tun könnten, ist, die (kommende)
QUERY
http-Methode, verlangen einen Request-Header, der der (sha256?) Hash der Anfrage sein muss, und antworten dann mitVary: Your-Hash-Header
. Dadurch wird sichergestellt, dass Clients, die Caching unterstützenQUERY
speichert verschiedene Cache-Einträge für verschiedene Stellen. Ich glaube, es ist ein Standard für Body-Hashes in Arbeit, aber ich kann ihn gerade nicht finden.2 Stimmen
OP hat eine nette Folgefrage zu dieser Frage geschrieben: evertpot.com/get-request-bodies
0 Stimmen
In Anbetracht all dieser Informationen wird mein Ansatz auch Informationen über die Annahme einer Stelle mit einer
GET
Anfrage in meinemOPTIONS
Antworten von der Serverseite und passe meine Anfrage entsprechend an. Der Server könnte diese Informationen aus einer Konfigurationsdatei lesen, zusammen mit allen anderen Informationen über seine Umgebung, oder er kann in regelmäßigen Abständen eine "get"-Anfrage an sich selbst senden, die einen Body enthält. Caching sollte durch einen Hash in der Anfrage-URI oder in einem Header gelöst werden. Proxy Awareness sollte in der Verantwortung des Frontends liegen.0 Stimmen
@toraman das ist eine Menge von Workarounds, nur um eine nicht standardisierte, falsche und wahrscheinlich immer noch brüchige Lösung zu erreichen. Warum machen Sie es nicht richtig?
0 Stimmen
@Evert ist das nicht korrekt? Ich sehe keinen Sinn darin, zusätzlich zu dem, was in den Spezifikationen steht, noch mehr Strenge hinzuzufügen. Die Worte
SHOULD
,SHOULDN'T
usw. sind definierte, technische Begriffe in diesen Spezifikationen, sie sind nicht passiv-aggressiv, wenn sie sagen, dass SieMAY
etwas tun. Die Vorgaben sind klar, man kann einen Körper haben, aber niemand muss ihn berücksichtigen. Das ist genau das, was ich hier zu erfüllen versuche. Meine Gründe sind unter anderem, dass ich in der Lage bin, zu unterscheiden zwischentrue
y"true"
oufalse
,null
,"false"
,undefined
,""
,{}
y[]
.0 Stimmen
@toraman haben Sie den Artikel gelesen, den ich darüber geschrieben habe? Ich habe es dort angesprochen. Es ist definitiv verwirrend: evertpot.com/get-request-bodies . Aber warum sollten Sie sich diese Mühe machen, wenn Sie einfach die
QUERY
Methode an. Es ist perfekt für diesen Zweck, und keine seltsamen Workarounds mitOPTIONS
oder das Risiko, dass Zwischenprodukte aus dem Körper fallen.0 Stimmen
Mir gefällt Ihre Auffassung darüber, was die Spezifikationen für uns bedeuten sollten, obwohl ich denke, dass sie gute Arbeit leisten.
QUERY
wird nicht annähernd so stark unterstützt wieGET
mit einer Leiche.fetch()
scheint eine Ausnahme zu sein, aber soweit es sich umfetch()
betrifft eine Methode namensGETBUTWITHABODY
ist genauso gültig wieQUERY
. Ich kann nicht herausfinden, welche Browser einen CacheQUERY
Antwort auf den Antrag, aber ich glaube nicht, dass viele das tun werden. Außerdem sehe ich nicht, dass viele Backend-Frameworks dies auch unterstützen. Ich würde gerne wechseln zuQUERY
aber noch nicht. Mein Workaround scheint derzeit zuverlässiger zu sein.