Ich muss eine RESTful-Abfrage-API entwerfen, die eine Reihe von Objekten basierend auf einigen Filtern zurückgibt. Die übliche HTTP-Methode hierfür ist GET. Das einzige Problem ist, dass es mindestens ein Dutzend Filter haben kann. Wenn wir alle als Abfrageparameter übergeben, kann die URL ziemlich lang werden (lang genug, um von einer Firewall blockiert zu werden).
Das Reduzieren der Anzahl von Parametern ist keine Option.
Eine Alternative, die ich mir vorstellen könnte, besteht darin, die POST-Methode für den URI zu verwenden und die Filter als Teil des POST-Körpers zu senden. Ist dies dagegen, RESTfull zu sein (POST-Aufruf zum Abfragen von Daten).
Hat jemand bessere Designvorschläge?
api
rest
http-parameters
missionE46
quelle
quelle
Antworten:
Denken Sie daran, dass bei einer REST-API alles eine Frage Ihrer Sichtweise ist.
Die beiden Schlüsselkonzepte in einer REST-API sind die Endpunkte und die Ressourcen (Entitäten). Ein Endpunkt gibt entweder Ressourcen über GET zurück oder akzeptiert Ressourcen über POST und PUT usw. (oder eine Kombination der oben genannten).
Es wird davon ausgegangen, dass mit POST die von Ihnen gesendeten Daten möglicherweise zur Erstellung einer neuen Ressource und der zugehörigen Endpunkte führen, die höchstwahrscheinlich nicht unter der POST-URL "leben". Mit anderen Worten, wenn Sie POSTEN, senden Sie Daten zur Bearbeitung an einen Ort. Auf dem POST-Endpunkt befindet sich die Ressource normalerweise nicht.
Zitat aus RFC 2616 (wobei irrelevante Teile weggelassen und relevante Teile hervorgehoben werden):
Wir haben uns an Endpunkte und Ressourcen gewöhnt, die "Dinge" oder "Daten" darstellen, sei es ein Benutzer, eine Nachricht, ein Buch - was auch immer die Problemdomäne vorschreibt. Ein Endpunkt kann jedoch auch eine andere Ressource verfügbar machen - beispielsweise Suchergebnisse.
Betrachten Sie das folgende Beispiel:
Dies ist ein typischer REST CRUD. Was aber, wenn wir hinzufügen:
An diesem Endpunkt ist nichts Unruhiges. Es akzeptiert Daten (Entitäten) in Form des Anforderungshauptteils. Diese Daten sind die Suchkriterien - ein DTO wie jedes andere. Dieser Endpunkt erzeugt eine Ressource (Entität) als Antwort auf die Anforderung: Suchergebnisse . Die Suchergebnisressource ist eine temporäre Ressource, die dem Client sofort ohne Weiterleitung und ohne Offenlegung durch eine andere kanonische URL bereitgestellt wird.
Es ist immer noch REST, außer dass die Entitäten keine Bücher sind - die Anforderungsentität sind Buchsuchkriterien und die Antwortentität sind Buchsuchergebnisse.
quelle
BooksSearchCriteriaDTO
und gehenBooksSearchResultsDTO
.POST
für den C-Teil von CRUD verwendet wird. Ich würde mit einfachen alten 200 gehen, optional vielleicht mit 204 für leere Suchergebnisse.Viele Leute haben die Praxis akzeptiert, dass ein GET mit einer zu langen oder zu komplexen Abfragezeichenfolge (z. B. Abfragezeichenfolgen verarbeiten verschachtelte Daten nicht einfach) stattdessen als POST gesendet werden kann, wobei die komplexen / langen Daten im Hauptteil dargestellt werden der Anfrage.
Suchen Sie in der HTTP-Spezifikation nach der POST-Spezifikation. Es ist unglaublich breit. (Wenn Sie ein Schlachtschiff durch eine Lücke in REST segeln möchten, verwenden Sie POST.)
Sie verlieren einige der Vorteile der GET-Semantik ... wie automatische Wiederholungsversuche, weil GET idempotent ist, aber wenn Sie damit leben können, ist es möglicherweise einfacher, die Verarbeitung wirklich langer oder komplizierter Abfragen mit POST zu akzeptieren.
(lol langer Exkurs ... Ich habe kürzlich festgestellt, dass GET nach der HTTP-Spezifikation einen Dokumententext enthalten kann . In einem Abschnitt heißt es umschrieben: "Jede Anfrage kann einen Dokumententext haben, mit Ausnahme der in diesem Abschnitt aufgeführten" ... und der Abschnitt, auf den es verweist, listet keinen auf. Ich habe einen Thread gesucht und gefunden, in dem die HTTP-Autoren darüber gesprochen haben, und es war beabsichtigt, damit Router und dergleichen nicht zwischen verschiedenen Nachrichten unterscheiden müssen Üben Sie, dass viele Infrastrukturelemente den Körper eines GET fallen lassen. Sie könnten also mit im Körper dargestellten Filtern wie POST mit GET arbeiten, aber Sie würden würfeln.)
quelle
Kurz gesagt: Erstellen Sie einen POST, überschreiben Sie jedoch die HTTP-Methode mithilfe des X-HTTP-Method-Override- Headers.
Echte Anfrage
POST / Bücher
Körper der Entität
{"title": "Ipsum", "year": 2017}
Überschriften
X-HTTP-Methodenüberschreibung: GET
Überprüfen Sie auf der Serverseite, ob der Header X-HTTP-Method-Override vorhanden ist, und nehmen Sie seinen Wert als Methode zum Erstellen der Route zum endgültigen Endpunkt im Backend. Nehmen Sie auch den Entitätstext als Abfragezeichenfolge. Aus Backend-Sicht wurde die Anfrage nur zu einem einfachen GET.
Auf diese Weise halten Sie das Design im Einklang mit den REST-Prinzipien.
Bearbeiten: Ich weiß, dass diese Lösung ursprünglich dazu gedacht war, das PATCH-Verbproblem in einigen Browsern und Servern zu lösen, aber sie funktioniert auch mit dem GET-Verb bei einer sehr langen URL, bei der es sich um das in der Frage beschriebene Problem handelt.
quelle
X-
Entfernung und 1.5. Bestehende Spezifikationen werden nicht überschrieben. ...X-
wird IMO hier bleiben.Wenn Sie in Java und JAX-RS entwickeln, empfehle ich Ihnen, @QueryParam mit @GET zu verwenden
Ich hatte die gleiche Frage, als ich eine Liste durchgehen musste.
Siehe Beispiel:
URI-Muster: „poc / test? Code = 1 & code = 2 & code = 3
@QueryParam konvertiert den Abfrageparameter "orderBy = age & orderBy = name" automatisch in java.util.List.
quelle