Ich suche nach einer vernünftigen Möglichkeit, Suchanfragen als RESTful-URLs darzustellen.
Das Setup: Ich habe zwei Modelle, Autos und Garagen, bei denen Autos in Garagen sein können. Meine URLs sehen also so aus:
/car/xxxx
xxx == car id
returns car with given id
/garage/yyy
yyy = garage id
returns garage with given id
Ein Auto kann alleine existieren (daher das / Auto) oder es kann in einer Garage existieren. Was ist der richtige Weg, um beispielsweise alle Autos in einer bestimmten Garage darzustellen? Etwas wie:
/garage/yyy/cars ?
Wie wäre es mit der Vereinigung von Autos in Garage JJJ und ZZZ?
Wie kann eine Suche nach Autos mit bestimmten Attributen richtig dargestellt werden? Sprich: Zeig mir alle blauen Limousinen mit 4 Türen:
/car/search?color=blue&type=sedan&doors=4
oder sollte es stattdessen / autos sein?
Die Verwendung von "Suche" scheint dort unangemessen - was ist ein besserer Weg / Begriff? Sollte es nur sein:
/cars/?color=blue&type=sedan&doors=4
Sollten die Suchparameter Teil von PATHINFO oder QUERYSTRING sein?
Kurz gesagt, ich suche nach Anleitungen für das modellübergreifende REST-URL-Design und für die Suche.
[Update] Ich mag Justins Antwort, aber er behandelt den Mehrfeld-Suchfall nicht:
/cars/color:blue/type:sedan/doors:4
oder etwas ähnliches. Wie gehen wir weiter?
/cars/color/blue
zum Mehrfeldfall?
/cars
und/car
nicht semantisch ist und daher eine schlechte Idee. Verwenden Sie immer den Plural, wenn sich mehr als ein Element in dieser Kategorie befindet.Antworten:
Verwenden Sie für die Suche Querystringe. Das ist vollkommen RESTful:
Ein Vorteil von regulären Abfrageringen besteht darin, dass sie Standard sind und allgemein verstanden werden und dass sie aus Form-Get generiert werden können.
quelle
/cars?color=whatever
./cars?color=blue&type=sedan&doors=4/engines
wird nicht funktionieren/cars?param=value
dient zum einfachen Filtern in der Fahrzeugliste und/cars/search?param=value
zum Erstellen einer Suche (mit oder ohne Beständigkeit), bei der das Ergebnis Suchbewertungen, Kategorisierungen usw. enthalten kann. Sie können auch eine benannte Suche wie erstellen / löschen/cars/search/mysearch
. Schauen Sie sich das an: stackoverflow.com/a/18933902/1480391Beim hübschen RESTful-URL-Design geht es darum, eine Ressource basierend auf einer Struktur anzuzeigen (verzeichnisähnliche Struktur, Datum: Artikel / 2005/5/13, Objekt und seine Attribute, ..). Der Schrägstrich
/
zeigt eine hierarchische Struktur an-id
stattdessen die.Hierarchische Struktur
Ich persönlich würde es vorziehen:
Wenn ein Benutzer das
/car-id
Teil entfernt, wird diecars
Vorschau angezeigt - intuitiv. Der Benutzer weiß genau, wo er sich im Baum befindet und worauf er schaut. Er weiß vom ersten Blick an, dass Garagen und Autos in Beziehung stehen./car-id
bedeutet auch, dass es im Gegensatz zu zusammen gehört/car/id
.Suchen
Die Suchabfrage ist in Ordnung , es gibt nur Ihre Präferenz, was berücksichtigt werden sollte. Der lustige Teil kommt beim Beitreten zu Suchanfragen (siehe unten).
Oder im Grunde alles, was kein Schrägstrich ist, wie oben erklärt.
Die Formel :
/cars[?;]color[=-:]blue[,;+&]
, * obwohl ich das&
Zeichen nicht verwenden würde , da es auf den ersten Blick nicht aus dem Text erkennbar ist.Liste der Optionen
mögliche Funktionen?
Suchzeichenfolgen negieren (!)
So suchen Sie nach Autos, aber nicht nach Schwarz und Rot :
?color=!black,!red
color:(!black,!red)
Neues Profil Suchen
Suchen rot oder blau oder schwarz Autos mit 3 Türen in Garagen ID 1..20 oder 101..103 oder 999 , aber nicht 5
/garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
Sie können dann komplexere Suchanfragen konstruieren. (Schauen Sie sich die CSS3-Attributübereinstimmung an, um die Idee zum Abgleichen von Teilzeichenfolgen zu finden. Suchen Sie beispielsweise nach Benutzern, die "bar" enthalten.
user*=bar
.)Fazit
Auf jeden Fall könnte dies der wichtigste Teil für Sie sein, denn Sie können es tun, wie Sie möchten. Denken Sie jedoch daran, dass RESTful URI eine Struktur darstellt, die leicht zu verstehen ist, z. B. verzeichnisartig
/directory/file
./collection/node/item
, Daten/articles/{year}/{month}/{day}
.. Und wenn man weglassen In jedem der letzten Segmente wissen Sie sofort, was Sie erhalten.Also .., alle diese Zeichen dürfen nicht codiert werden :
a-zA-Z0-9_.-~
Regel zulässig, sowohl codiert als auch nicht, sind beide Verwendungen gleichwertig.
$-_.+!*'(),
;/?:@=&
Kann für den von ihnen dargestellten Zweck unverschlüsselt verwendet werden, andernfalls müssen sie verschlüsselt werden.
unsicher:
<>"#%{}|\^~[]`
Warum unsicher und warum sollte lieber codiert werden: RFC 1738 siehe 2.2
Weitere Zeichenklassen finden Sie auch in RFC 1738 # Seite 20 .
RFC 3986 siehe 2.2
Trotz allem, was ich zuvor gesagt habe, gibt es hier eine allgemeine Unterscheidung von Begrenzern, was bedeutet, dass einige " wichtiger " sind als andere.
:/?#[]@
!$&'()*+,;=
Weitere Informationen:
Hierarchie: siehe 2.3 , siehe 1.2.3
URL-Pfadparametersyntax
CSS3-Attributübereinstimmung
IBM: RESTful Web Services - Die Grundlagen
Hinweis: RFC 1738 wurde von RFC 3986 aktualisiert
quelle
POST
. Auch andere Ideen, die Sie in Ihrer Antwort angegeben haben, sind sehr wertvoll. Vielen Dank!;
im Gegensatz zu&
ist die Lesbarkeit? Denn wenn ja, würde ich das eigentlich bevorzugen,&
da es das üblichere Trennzeichen ist ... richtig? :) Vielen Dank!&
als Trennzeichen nur Entwicklern bekannt ist. Eltern, Großeltern und die nicht-it-gebildete Bevölkerung akzeptieren Trennzeichen, wie sie in allgemein geschriebenen Texten verwendet werden.Obwohl es einige Vorteile hat, die Parameter im Pfad zu haben, gibt es IMO einige überwiegende Faktoren.
Nicht alle für eine Suchabfrage benötigten Zeichen sind in einer URL zulässig. Die meisten Interpunktions- und Unicode-Zeichen müssten als Abfragezeichenfolgenparameter URL-codiert sein. Ich ringe mit dem gleichen Problem. Ich möchte XPath in der URL verwenden, aber nicht alle XPath-Syntax ist mit einem URI-Pfad kompatibel. Für einfache Pfade
/cars/doors/driver/lock/combination
wäre es daher angebracht, dascombination
Element ' ' im XML-Dokument der Fahrertür zu lokalisieren . Ist/car/doors[id='driver' and lock/combination='1234']
aber nicht so freundlich.Es gibt einen Unterschied zwischen dem Filtern einer Ressource anhand eines ihrer Attribute und dem Angeben einer Ressource.
Zum Beispiel seit
/cars/colors
Gibt eine Liste aller Farben für alle Autos zurück (die zurückgegebene Ressource ist eine Sammlung von Farbobjekten)./cars/colors/red,blue,green
würde eine Liste von Farbobjekten zurückgeben, die rot, blau oder grün sind, keine Sammlung von Autos.Um Autos zurückzugeben, wäre der Weg
/cars?color=red,blue,green
oder/cars/search?color=red,blue,green
Parameter im Pfad sind schwieriger zu lesen, da Name / Wert-Paare nicht vom Rest des Pfads isoliert sind, bei dem es sich nicht um Name / Wert-Paare handelt.
Ein letzter Kommentar. Ich bevorzuge
/garages/yyy/cars
(immer Plural)/garage/yyy/cars
(vielleicht war es ein Tippfehler in der ursprünglichen Antwort), weil es vermeidet, den Pfad zwischen Singular und Plural zu ändern. Bei Wörtern mit einem hinzugefügten 's' ist die Änderung nicht so schlecht, aber das Ändern/person/yyy/friends
in/people/yyy
scheint umständlich zu sein.quelle
Um Peters Antwort zu erweitern, könnten Sie Search zu einer erstklassigen Ressource machen:
Die Suchressource enthält Felder für Farbe, Modell erstellen, Garagenstatus usw. und kann in XML, JSON oder einem anderen Format angegeben werden. Wie bei der Ressource Auto und Garage können Sie den Zugriff auf Suchvorgänge basierend auf der Authentifizierung einschränken. Benutzer, die häufig dieselben Suchvorgänge ausführen, können sie in ihren Profilen speichern, sodass sie nicht neu erstellt werden müssen. Die URLs sind so kurz, dass sie in vielen Fällen problemlos per E-Mail gehandelt werden können. Diese gespeicherten Suchvorgänge können die Grundlage für benutzerdefinierte RSS-Feeds usw. sein.
Es gibt viele Möglichkeiten, Suchen zu verwenden, wenn Sie sie als Ressourcen betrachten.
Die Idee wird in diesem Railscast näher erläutert .
quelle
Justins Antwort ist wahrscheinlich der richtige Weg, obwohl es in einigen Anwendungen sinnvoll sein kann, eine bestimmte Suche als eigenständige Ressource zu betrachten, z. B. wenn Sie benannte gespeicherte Suchvorgänge unterstützen möchten:
oder
quelle
Ich verwende zwei Ansätze, um Suchvorgänge zu implementieren.
1) Einfachster Fall, um zugeordnete Elemente abzufragen und zur Navigation.
Dies bedeutet, dass Fahrzeuge mit einer Garagen-ID von 1 abgefragt werden müssen.
Es ist auch möglich, komplexere Suchvorgänge zu erstellen:
Autos in allen Garagen in FirstStreet, die nicht rot sind (3. Seite, 100 Elemente pro Seite).
2) Komplexe Abfragen werden als reguläre Ressourcen betrachtet, die erstellt werden und wiederhergestellt werden können.
Der POST-Text für die Sucherstellung lautet wie folgt:
Es basiert auf Grails (Kriterien DSL): http://grails.org/doc/2.4.3/ref/Domain%20Classes/createCriteria.html
quelle
Dies ist kein REST. Sie können keine URIs für Ressourcen in Ihrer API definieren. Die Ressourcennavigation muss hypertextgesteuert sein. Es ist in Ordnung, wenn Sie hübsche URIs und viel Kopplung wünschen, aber nennen Sie es einfach nicht REST, da es direkt gegen die Einschränkungen der RESTful-Architektur verstößt.
Siehe diesen Artikel des Erfinders von REST.
quelle
Obwohl mir Justins Antwort gefällt, ist sie meiner Meinung nach eher ein Filter als eine Suche. Was ist, wenn ich etwas über Autos mit Namen wissen möchte, die mit cam beginnen?
So wie ich es sehe, können Sie es in den Umgang mit bestimmten Ressourcen einbauen:
/ cars / cam *
Oder Sie können es einfach in den Filter einfügen:
/ cars / door / 4 / name / cam * / colours / red, blau, grün
Ich persönlich bevorzuge letzteres, bin aber keineswegs ein Experte für REST (nachdem ich erst vor ungefähr zwei Wochen davon gehört habe ...)
quelle
/cars?name=cam*
RESTful empfiehlt nicht, Verben in URLs zu verwenden. / Cars / search ist nicht erholsam. Der richtige Weg zum Filtern / Suchen / Paginieren Ihrer APIs sind Abfrageparameter. Es kann jedoch Fälle geben, in denen Sie die Norm brechen müssen. Wenn Sie beispielsweise über mehrere Ressourcen hinweg suchen, müssen Sie so etwas wie / search? Q = query verwenden
Unter http://saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices/ finden Sie die Best Practices für das Entwerfen von RESTful-APIs
quelle
Darüber hinaus würde ich auch vorschlagen:
Hier
Search
wird als untergeordnete Ressource derCars
Ressource betrachtet.quelle
Hier gibt es viele gute Möglichkeiten für Ihren Fall. Sie sollten dennoch in Betracht ziehen, den POST-Body zu verwenden.
Die Abfragezeichenfolge ist perfekt für Ihr Beispiel. Wenn Sie jedoch etwas Komplizierteres haben, z. B. eine beliebig lange Liste von Elementen oder boolesche Bedingungen, möchten Sie den Beitrag möglicherweise als Dokument definieren, das der Client über POST sendet.
Dies ermöglicht eine flexiblere Beschreibung der Suche und vermeidet die Begrenzung der Server-URL-Länge.
quelle
Mein Rat wäre:
Bearbeiten:
Hoffentlich kommt Ihnen das auf die Idee. Im Wesentlichen sollte Ihre Rest-API leicht erkennbar sein und Ihnen das Durchsuchen Ihrer Daten ermöglichen. Ein weiterer Vorteil bei der Verwendung von URLs und nicht von Abfragezeichenfolgen besteht darin, dass Sie die auf dem Webserver vorhandenen nativen Caching-Mechanismen für den HTTP-Verkehr nutzen können.
Hier ist ein Link zu einer Seite, die die Übel von Abfragezeichenfolgen in REST beschreibt: http://web.archive.org/web/20070815111413/http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
Ich habe den Google-Cache verwendet, weil die normale Seite für mich nicht funktioniert hat. Hier ist auch dieser Link: http://rest.blueoxen.net/cgi-bin/wiki.pl?QueryStringsConsideredHarmful
quelle
/cars/colors/red,blue,green
und kennen/cars/colors/green,blue,red
? Das Pfadelement der URI sollte hierarchisch sein, und ich sehe das hier nicht wirklich. Ich denke, dies ist eine Situation, in der die Abfragezeichenfolge die am besten geeignete Wahl ist.