REST - Kompromisse zwischen Inhaltsaushandlung über Accept-Header und Erweiterungen

40

Ich arbeite an der Entwicklung einer RESTful-API. Wir wissen, dass wir JSON und XML für eine bestimmte Ressource zurückgeben möchten. Ich hatte gedacht, wir würden so etwas machen:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

Jemand hat jedoch die Verwendung von Erweiterungen für dieses Problem ausgeschlossen, z. B .:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Was sind die Kompromisse mit diesen Ansätzen? Verlassen Sie sich am besten auf den Accept-Header, wenn keine Erweiterung angegeben ist, und berücksichtigen Sie die angegebenen Erweiterungen? Hat dieser Ansatz einen Nachteil?

Brandon Linton
quelle
Welchen Webserver benutzt du? und wie werden URLs analysiert?
Dipan Mehta
1
Ich habe keine Ahnung von der technischen (Server-) Seite der Dinge. Abgesehen davon bevorzuge ich Ihren Ansatz, da er den HTTP-Standard verwendet, der das Verständnis erleichtert (zum Beispiel, wenn jemand anderes einige Jahre später Wartungsarbeiten daran vornehmen soll). Sie können sich auf die Erweiterung verlassen, wenn das Accept nicht angegeben ist oder einen unerwarteten Wert hat, aber ich würde immer zuerst mit dem Standard verfahren.
Treb
@ Dipan Ich hacke dies mit der MVC4-Web-API (noch in der Beta). Es werden die hübschen ASP.NET-Routing-Abstraktionen verwendet.
Brandon Linton
1
@Treb Ja, ich bin viel mehr ein Fan der Verwendung des Accept-Header-Werts. Ich frage mich, ob es einen Nachteil gibt, beide zu unterstützen.
Brandon Linton

Antworten:

38

Dies ist jedoch "philosophisch gesehen - der erste Ansatz ist der einzige Ansatz" und dieser "der richtige offizielle REST-Ansatz ist die Verwendung von Accept: header". werden weithin als der Fall angesehen, sind aber auch absolut falsch .

Hier ist ein kurzer Ausschnitt von Roy Fielding (der REST definiert hat) ...

"Abschnitt 6.2.1 besagt nicht, dass die Inhaltsaushandlung immer verwendet werden sollte." zitieren

Diese spezielle Konversation befindet sich im Kontext der Überschrift "Accept-Language:", das Gleiche gilt jedoch auch für die Überschrift "Accept:", wie später in seiner Antwort klargestellt wird ...

"Ich habe keine Ahnung, warum die Leute den zweiten und dritten Link auf der oberen Seite nicht sehen können

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

dieser Punkt auf die beiden PDF-Ausgaben. "

Damit ist gemeint, dass es kein Problem ist, unterschiedliche Endpunkte für unterschiedliche Darstellungen derselben Quelldaten zu verwenden. (In diesem Fall ein HTML-Endpunkt und zwei verschiedene PDF-Endpunkte.)

Ebenfalls in einer ähnlichen Diskussion, diesmal in Bezug auf die Vorteile der Verwendung von Abfrageparametern im Vergleich zur Verwendung von Dateierweiterungen für verschiedene Medientypen ...

"Deshalb bevorzuge ich immer Erweiterungen. Keine der beiden Optionen hat etwas mit REST zu tun." zitieren

Auch dies unterscheidet sich geringfügig von den Dateierweiterungen "Akzeptieren" und "Dateiname", doch die Haltung von Fielding ist weiterhin klar.

Antwort - es ist wirklich egal. Die Kompromisse zwischen den beiden sind nicht sehr bedeutend und beide sind akzeptable Stile.

Tom Christie
quelle
3
Sehr ausgewogene Antwort. Ich denke, ich würde manchmal hinzufügen, dass es aus der URI "offensichtlich" ist, dass ein bestimmter Inhalt beabsichtigt ist. zB .html-Erweiterung oder .pdf-Erweiterung in der URI. In diesem Fall muss die Inhaltsverhandlung nicht unbedingt unterstützt werden, und wenn der Inhalt in der URI enthalten ist, können Menschen die URI leichter freigeben und sie verwenden, um Verknüpfungen zu Dingen herzustellen, die sie sofort nutzen können. In anderen Fällen, z. B. wenn Sie Erweiterungen in Ihren URIs vermeiden und / oder eine Web-API verfügbar machen möchten, die mehrere Inhaltstypen json / XML gleichermaßen unterstützt, kann ein Accept-Header besser passen.
Tim Lovell-Smith
Die Antwort wurde aktualisiert und enthält nun neue Links. Ich denke, Yahoo-Gruppen haben ihre Struktur geändert.
Phil Stör
Ich stimme dir nicht zu. Die vom Server zurückgegebene Ressourcenbeschreibungssprache sollte für die vom Service-Endpunkt ausgeführte Geschäftslogik irrelevant sein. Es scheint ein Missverständnis darüber zu sein, wie REST-URIs erstellt werden sollten, wenn mehrere URIs für denselben Service-Endpunkt vorhanden sind, nur um unterschiedliche Ressourcenbeschreibungssprachen zu berücksichtigen.
Dejay Clayton
10

Der richtige offizielle RESTful-Ansatz ist die Verwendung von Accept:Header.

Sie müssen jedoch darauf achten, die Cachefähigkeit nicht zu beschädigen, was eine der Anforderungen von REST ist. Sie müssen Vary: AcceptHeader und Cache haben, die es verstehen. In der idealen Welt hättest du es, aber im wirklichen Leben kann deine Hirse variieren. Die zweite Lösung ist also nicht so sauber, könnte aber praktischer sein.

Beachten Sie auch, dass einige sehr alte Browser zum Ignorieren von Headern verwendet wurden und stattdessen auf der Erweiterung basieren.

vartec
quelle
1
Faktisch ungenau. Siehe akzeptierte Antwort.
Phil Stör
9

Technisch spielt es eigentlich keine Rolle - Ihr Webserver wird in der Lage sein, den Prozess so auszuführen, wie er aussieht. (Ich gehe davon aus, sehe aber nicht wie ein Showstopper aus).

Philosophisch gesehen ist der erste Ansatz der einzige. In REST verweist die URL tatsächlich nur auf einen URI - bei dem es sich nur um eine Ressource handelt. Stellen Sie sich diese Ressource für einen Moment genauso vor wie das Objekt in der objektorientierten Programmierung. Sie sprechen mit dieser Ressource über nur 4 Methoden (auch bekannt als GET / POST / PUT / DELETE - oder wenn irgendetwas, das der Transport zulässt), aber diese Methode wird nicht zur Beschreibung des Objekts. Ebenso ist der Rückgabewert nicht der URI. Das Objekt ist immer noch etwas und nicht something.xml oder something.json

Angenommen, wenn Sie den Accept-Header nicht verwenden möchten, aber trotzdem wirklich REST-philosophisch sein möchten, stört mich Folgendes nicht:

GET /api/something?parm1=value1&return_type=xml

im Gegensatz zu

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Aber wie gesagt, dieser Unterschied ist nur philosophisch.

Dipan Mehta
quelle
+1 Dipan, du hast recht, mit einer Ausnahme: / api / something? Return_type = xml ist immer noch nicht erholsam . Der Grund, warum es nicht RESTful ist, ist, dass URLs undurchsichtig sind. Aus protokollarischer Sicht gibt es keinen Unterschied zwischen / api / something / xml und / api / something? Xml. Siehe w3.org/DesignIssues/Axioms.html .
Mark E. Haase
0

@vartec: Ich denke du liegst falsch

Das richtige offizielle RESTful-Prinzip besagt, dass in HTTP-Headern nichts verborgen sein sollte, da der URI offengelegt oder referenziert wird. Alle Details zu der Anforderung / Antwort sollten als Teil des URI bereitgestellt werden

Daher empfehle ich dringend, keine Header zu verwenden, um Details über die Anfrage und die Antwort zu erhalten

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Ich bin die Referenzen nicht in der Lage schnell zu finden, aber ich werde mit ihnen Post zurück (eigentlich Sie den O'reilly Veröffentlichung Buch „RESTful Web Service“ beziehen könnten ( http://shop.oreilly.com/product/9780596529260.do ) das bestätigt das selbe

Basav
quelle
17
-1 Völlig falsch. Für eine Sache, die URL wird in den HTTP - Header gesendet. Darüber hinaus sollte jede URL eine eigene Ressource darstellen. XML- und JSON-Codierungen mit demselben Inhalt sind eindeutig keine zwei verschiedenen Ressourcen. Es handelt sich um zwei verschiedene Darstellungen derselben Ressource.
Mark E. Haase
HTTP-Header sind ein legitimer und empfohlener Ort zum Speichern von "Messaging-Metadaten", z. B .: Sicherheitsanmeldeinformationen, Korrelationskennung, Sitzungs-ID, Transaktionskontext, Datenformate. Diese Art von Informationen sollte Ihre URLs oder Ihre Nachrichtennutzlast nicht überladen.
Paulo Merson