it-swarm.com.de

Entwerfen Sie eine RESTful-Abfrage-API mit einer langen Liste von Abfrageparametern

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).

Die Reduzierung der Parameteranzahl ist keine Option.

Eine Alternative, die ich mir vorstellen könnte, ist, die POST -Methode für den URI zu verwenden und die Filter als Teil des POST Body zu senden. Ist das gegen das Sein? RESTfull (Durchführen eines POST Aufrufs zum Abfragen von Daten).

Hat jemand bessere Designvorschläge?

129
missionE46

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). Locker ausgedrückt gibt ein Endpunkt Ressourcen entweder über GET zurück oder akzeptiert Ressourcen über POST = und PUT und so weiter (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 unter der POST-URL höchstwahrscheinlich nicht "aktiv" sind. Mit anderen Worten, wenn Sie POST Sie senden Daten irgendwo zur Bearbeitung. Der POST Endpunkt ist nicht der Ort, an dem sich die Ressource normalerweise befindet.

Zitat aus RFC 2616 (irrelevante Teile weggelassen und relevante Teile hervorgehoben):

9.5 POST

Die Methode POST wird verwendet, um den Origin-Server aufzufordern, die in der Anfrage enthaltene Entität als neuen Untergebenen der durch den Request-URI in der Anfragezeile angegebenen Ressource zu akzeptieren. POST soll eine einheitliche Methode ermöglichen, um die folgenden Funktionen abzudecken:

  • ...
  • Bereitstellung eines Datenblocks, z. B. des Ergebnisses der Übermittlung eines Formulars, für einen Datenverarbeitungsprozess;
  • ...

...

Die von der POST method ausgeführte Aktion führt möglicherweise nicht zu einer Ressource, die durch einen URI identifiziert werden kann. In diesem Fall ist entweder 200 (OK) oder 204 (Kein Inhalt) der geeignete Antwortstatus, abhängig von ob die Antwort eine Entität enthält, die das Ergebnis beschreibt.

Wenn eine Ressource auf dem Origin-Server erstellt wurde, MUSS die Antwort 201 (Erstellt) lauten.

Wir haben uns immer mehr an Endpunkte und Ressourcen gewöhnt, die "Dinge" oder "Daten" darstellen, sei es ein Benutzer, eine Nachricht, ein Buch - ganz gleich, welche Problemdomäne dies vorschreibt. Ein Endpunkt kann jedoch auch eine andere Ressource verfügbar machen - beispielsweise Suchergebnisse.

Betrachten Sie das folgende Beispiel:

GET    /books?author=AUTHOR
POST   /books
PUT    /books/ID
DELETE /books/ID

Dies ist eine typische REST CRUD. Was aber, wenn wir hinzufügen:

POST /books/search

    {
        "keywords": "...",
        "yearRange": {"from": 1945, "to": 2003},
        "genre": "..."
    }

An diesem Endpunkt ist nichts Unerwartetes. Es akzeptiert Daten (Entitäten) in Form des Anforderungskörpers. Diese Daten sind die Suchkriterien - ein DTO wie jeder andere. Dieser Endpunkt erzeugt eine Ressource (Entität) als Antwort auf die Anforderung: Suchergebnisse. Die Ressource für Suchergebnisse ist eine temporäre Ressource, die dem Kunden sofort ohne Weiterleitung und ohne Angabe einer anderen kanonischen URL zur Verfügung gestellt 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.

110
Amir Abiri

Viele Leute haben die Praxis akzeptiert, dass ein GET mit einer zu langen oder zu komplexen Abfragezeichenfolge (z. B. Abfragezeichenfolgen, die verschachtelte Daten nicht einfach verarbeiten) als POST stattdessen mit gesendet werden kann die komplexen/langen Daten, die im Hauptteil der Anforderung enthalten sind.

Die Spezifikation für POST in der HTTP-Spezifikation. Sie 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, nur die Verarbeitung sehr langer oder komplizierter Abfragen mit POST zu akzeptieren.

(lol langer Exkurs ... Ich habe kürzlich festgestellt, dass GET can in der HTTP-Spezifikation einen Dokumenttext enthält. In einem Abschnitt heißt es umschrieben: "Jede Anfrage kann einen Dokumenttext enthalten, mit Ausnahme der aufgelisteten in diesem Abschnitt "... und der Abschnitt, auf den er 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 differenzieren müssen zwischen verschiedenen Nachrichten. In der Praxis lassen jedoch viele Infrastrukturelemente den Hauptteil eines GET fallen. Sie könnten also mit im Hauptteil dargestellten Filtern, wie POST, GET ausführen, aber Sie würfeln.)

72
Rob

Kurz gesagt: Erstellen Sie eine POST aber überschreiben Sie die HTTP-Methode mit dem X-HTTP-Method-Override -Header.

Echte Bitte

POST/Bücher

Entitätskörper

{"title": "Ipsum", "year": 2017}

Header

X-HTTP-Methoden-Override: GET

Überprüfen Sie auf der Serverseite, ob der Header "X-HTTP-Method-Override" vorhanden ist, und verwenden Sie seinen Wert als Methode zum Erstellen der Route zum endgültigen Endpunkt im Backend. Nehmen Sie außerdem den Entitätstext als Abfragezeichenfolge. Aus Sicht des Backends wurde die Anfrage einfach zu einem GET.

Auf diese Weise halten Sie das Design im Einklang mit den REST Grundsätzen.

Edit: Ich weiß, dass diese Lösung ursprünglich dazu gedacht war, das PATCH-Verb-Problem in einigen Browsern und Servern zu lösen, aber es funktioniert auch mit dem GET-Verb, wenn die URL sehr lang ist Frage.

6
Delmo