Best Practice für REST-API-Aufruf mit vielen Parametern

11

Ich habe eine REST-API mit GETs-Operationen, die eine (lange) Liste von Parametern erhalten (z. B. 8 Parameter). Ziel dieser Operation ist es, Elemente zu suchen und zu filtern.

Welches ist die beste Vorgehensweise, um dieses Szenario zu verwalten?:

(1) Eine Liste von Parametern erhalten?:

public ResultType Get(int p1, int p2, string p3...) { ... }

(2) Oder ein Objekt empfangen , das diese Parameter kapselt ?:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }
    public string Z { get; set; }
}

public ResultType Get(MyClass parameter) { ... }

Denken Sie an ein E-Commerce-Szenario, in dem Sie "Produkte" nach Name, Beschreibung, Kategorie, Marke, Modell, Preis usw. suchen und filtern möchten.

Jose Alonso Monge
quelle
1
Die Position ist weniger ein Bezeichner als ein Eigenname für einen Wert.
SD
Warum haben Sie 8 Parameter? Was machen Sie? Gibt es eine Entscheidungslogik (und ist es ein Chaos)? Können Sie diese API / Methode in mehrere Methoden aufteilen, die 3 oder 4 Parameter annehmen?
Filip Milovanović
1
8 Parameter ist nur ein Beispiel. Meine Get-Operation ist eine "Such" -Methode. Denken Sie an ein E-Commerce-Szenario, in dem Sie "Produkte" nach Name, Beschreibung, Kategorie, Marke, Modell, Preis usw. suchen und filtern möchten. Ich habe die Frage bearbeitet, um den Kontext hinzuzufügen
Jose Alonso Monge

Antworten:

10

Ich habe eine REST-API mit GETs-Operationen, die eine (lange) Liste von> Parametern erhalten. Welches ist die beste Vorgehensweise, um dieses Szenario zu verwalten?

AFAIK, es gibt keine fest etablierten Best Practices (sorry). Man kann jedoch einige Empfehlungen aussprechen:

  • Versuchen Sie zu vermeiden , mitPOST (statt GET) , wenn die Anfrage ist sicher (dh nebenwirkungsfreie, insbesondere keine Daten zu ändern). Wenn die Parameter sehr groß sind, müssen Sie möglicherweise POSTLängenbeschränkungen umgehen. Dies ist jedoch normalerweise kein Problem (die meisten Programme unterstützen recht lange URLs), und sichere Anforderungen sollten verwendet werdenGET , um Optimierungen wie Caching und Prefetching zu ermöglichen.

  • Wenn Sie verwenden GET, müssen Sie Ihre Parameter als URL-Parameter senden 1) . In dieser Situation besteht die natürliche und übliche Lösung darin, eine Liste von Parametern zu verwenden. Daher würde ich dies empfehlen. Ja, die Liste wird lang sein, aber die REST-API ist (wahrscheinlich) für die programmatische Verwendung vorgesehen, sodass ich hier kein Problem sehe. Benutzer der API können die Parameter in einem Objekt in ihrem eigenen Code kapseln.

  • Technisch gesehen könnten Sie ein Objekt auch in einen URL-Parameter einfügen (wie JSON, XML oder was auch immer), aber das ist ungewöhnlich, daher würde ich es nach Möglichkeit vermeiden.

1) Genau genommen können Sie einen Körper mit einer GETAnfrage verwenden, dies ist jedoch ungewöhnlich und wird im Allgemeinen nicht empfohlen. siehe zB HTTP GET mit Anforderungshauptteil .


Ebenso wie bei Methoden im Quellcode, die lange Parameterlisten enthalten, möchten Sie möglicherweise prüfen, ob die REST-API ein Refactoring benötigt. Genau wie im Quellcode zeigt eine so lange Parameterliste an, dass der API-Endpunkt viele verschiedene Dinge tut. Ist es vielleicht sinnvoll, es aufzuteilen oder Standardeinstellungen vorzunehmen? Aber das ist eine andere Frage ...

sleske
quelle
Technisch gesehen können Sie auch einen Körper mit einem GET senden, obwohl ungewöhnlich
Ewan
Sind Sie sicher, dass Sie idempotent meinen? Ich würde sagen, dass 'cachefähig' GetTodaysDayName () als idempotent angesehen werden kann, aber Sie möchten es nicht zwischenspeichern
Ewan
Lass den Kampf zwischen GET und POST beginnen !!!! :)
Ewan
@Ewan: Zum Zwischenspeichern von GetTodaysDayName: Angenommen, Sie benötigen den heutigen Namen zehnmal pro Sekunde und möchten nicht einige Sekunden lang den falschen Tag verwenden, möchten Sie ihn höchstwahrscheinlich zwischenspeichern. Trotzdem habe ich fälschlicherweise "idempotent" verwendet, was ich im Sinn hatte, war "sicher" (= nicht modifizierend). Bearbeitet.
Sleske
1
@Ewan konstruktive Schlachten, in denen die "Gegner" die gegenseitige Reaktion bereichern, sind mehr als willkommen. Vielen Dank an Sie beide für einen sehr umfassenden Überblick über alle Optionen!
Christophe
3

Es wird empfohlen, die Parameter als Objekt zu POSTEN.

Dadurch werden die URL-Längenbeschränkung und andere Probleme mit Abfragezeichenfolgen vermieden. Wenn Sie mehrere Parameter in JSON senden, ist ein Objekt die Standardmethode. Daher ist es sinnvoll, auf einen zu deserialisieren.

Sie können vermeiden, zufällige Anforderungsobjekte zu erstellen, die nur in Ihren Controllern verwendet werden, indem Sie auf Wunsch zu einem dynamischen Objekt deserialisieren. obwohl das anschließende Casting auf die richtigen Typen ebenso chaotisch sein kann.

Früher war es möglich, dass mehrere Parameter in Ihrer Controller-Aktion automatisch an die Felder eines eingehenden JSON-Objekts gebunden wurden. Dies funktioniert jedoch nicht mehr sofort im .net-Kern.

Obwohl es dies gibt, könnte ich versucht sein, es zu versuchen

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/application-model?view=aspnetcore-2.1#application-model-usage-in-webapicompatshim

Bearbeiten: Ich werde nur ein paar Punkte zur Verwendung von GET hinzufügen

  • Caching: GET wird von Clients zwischengespeichert, die der HTTP-Spezifikation entsprechen. Die Spezifikation soll jedoch das Laden von Webseiten beschleunigen. Das Caching ist hilfreich, wenn Ihr API-Ergebnis dieselben Cache-Anforderungen wie eine Webseite hat, aber nicht hilfreich, wenn dies nicht der Fall ist. Sie können bei Bedarf Ihr eigenes Caching von POST-Antworten im Client hinzufügen.

  • URL-Länge: Dies ist hauptsächlich ein Problem, wenn Sie ein Array senden. Offensichtlich kann ein Array leicht sehr lang werden und die Namen der Abfragezeichenfolgenparameter werden für jedes Element wiederholt. Selbst wenn Sie nur eine Zeichenfolge senden, kann diese Zeichenfolge technisch gesehen sehr, sehr lang sein.

  • Protokollierung: Standardmäßig protokollieren viele Webserver die gesamte Abfragezeichenfolge. Oft möchten Sie nicht, dass Parameterdaten in Nur-Text-Protokollen landen.

  • GET with body: Dies scheint die perfekte Antwort zu sein, die REST-Puristen zufriedenstellt und gleichzeitig eine schöne Datenstruktur zulässt. Es ist jedoch ungewöhnlich und verpönt, dass ein POST die Standardmethode zum Senden eines Körpers ist.

Ewan
quelle
2
Ich denke nicht, dass dies eine bewährte Methode ist. Insbesondere , wenn die Anforderung idempotent ist, es ist am beste Praxis zu nutzen GETund nicht PUT(für Cache - Fähigkeit, unter anderem). Und URL-Längenbeschränkungen sind heutzutage ziemlich groß, also nicht unbedingt ein Problem.
Sleske
@sleske Wenn du denkst, dass GET besser ist, solltest du eine Antwort darüber schreiben, warum. String z kann jedoch 4 MB lang sein
Ewan
Eigentlich nur googeln und die maximale Länge der JSON-Saite scheint ungewiss
Ewan
In Anbetracht des Kontexts müssen die Anforderungsparameter nicht in Ihren Protokollen enthalten sein - es sei denn, Sie möchten keine Analysen zu den auf Ihrer Seite gesuchten Personen durchführen;) GETist aus zwei Perspektiven völlig sinnvoll: a) Analysen und b) a Der Benutzer kann die Abfrage für später speichern oder freigeben.
Thomas Junk
@ThomasJunk Auf welchen Kontext beziehen Sie sich? Die Zeichenfolge heißt 'z', es könnte buchstäblich alles drin sein. Was ist die GDPR Geldstrafe 20 Millionen Dollar?
Ewan