REST-API-DESIGN - Abrufen einer Ressource über REST mit unterschiedlichen Parametern, aber demselben URL-Muster


92

Ich habe eine Frage zum REST-URL-Design. Ich habe hier einige relevante Beiträge gefunden: Verschiedene RESTful-Darstellungen derselben Ressource und hier: RESTful-URL zur GET-Ressource nach verschiedenen Feldern, aber die Antworten sind nicht ganz klar, was die Best Practices sind und warum. Hier ist ein Beispiel.

Ich habe REST-URLs zur Darstellung der Ressource "Benutzer". Ich kann einen Benutzer mit einer ID oder einer E-Mail-Adresse abrufen, aber die URL-Darstellung bleibt für beide gleich. Ich gehe viele Blogs und Bücher durch und sehe, dass die Leute dies auf viele verschiedene Arten getan haben. Beispielsweise

Lesen Sie diese Übung in einem Buch und irgendwo im Stackoverflow (ich kann den Link anscheinend nicht wiederfinden).

GET /users/id={id}
GET /users/email={email}

Lesen Sie diese Praxis in vielen Blogs

GET /users/{id}
GET /users/email/{email}

Abfrageparameter werden normalerweise zum Filtern der Ergebnisse der durch die URL dargestellten Ressourcen verwendet, aber ich habe gesehen, dass diese Vorgehensweise auch verwendet wird

GET /users?id={id}
GET /users?email={email}

Meine Frage ist, welche von all diesen Praktiken für Entwickler, die die API konsumieren, am sinnvollsten ist und warum? Ich glaube, es gibt keine in Stein gemeißelten Regeln, wenn es um REST-URL-Designs und Namenskonventionen geht, aber ich wollte nur wissen, welchen Weg ich einschlagen sollte, um Entwicklern zu helfen, die APIs besser zu verstehen.

Alle Hilfe geschätzt!


1
Ich weiß, dass dies ein wenig alt ist, aber auf der Suche nach ähnlichen Ressourcen stolpere ich über diese und die von Ihnen gesuchte Frage. Ich glaube, es ist dies ein stackoverflow.com/a/9743414/468327
Joel Berger

Antworten:


101

Nach meiner Erfahrung GET /users/{id} GET /users/email/{email}ist der häufigste Ansatz. Ich würde auch erwarten, dass die Methoden einen 404 Not Found zurückgeben, wenn ein Benutzer mit dem bereitgestellten idoder nicht existiert email. Ich wäre auch nicht überrascht zu sehen GET /users/id/{id}(obwohl es meiner Meinung nach überflüssig ist).

Kommentare zu den anderen Ansätzen

  1. GET /users/id={id} GET /users/email={email}
    • Ich glaube nicht, dass ich das gesehen habe, und wenn ich es gesehen hätte, wäre es sehr verwirrend. Es ist fast so, als würde versucht, Abfrageparameter mit Pfadparametern zu imitieren.
  2. GET /users?id={id} GET /users?email={email}
    • Ich denke, Sie haben den Nagel auf den Kopf getroffen, als Sie die Verwendung von Abfrageparametern zum Filtern erwähnt haben.
    • Wäre es jemals sinnvoll, diese Ressource sowohl mit einem idals auch mit einem email(z. B. GET /users?id={id}&email={email}) aufzurufen ? Wenn nicht, würde ich keine einzige Ressourcenmethode wie diese verwenden.
    • Ich würde erwarten, dass diese Methode zum Abrufen einer Liste von Benutzern mit optionalen Abfrageparametern zum Filtern verwendet wird, aber ich würde nicht erwarten id, emaildass eine eindeutige Kennung zu den Parametern gehört. Beispiel: GET /users?status=BANNEDGibt möglicherweise eine Liste der gesperrten Benutzer zurück.

Überprüfen Sie diese Antwort von einer verwandten Frage.


Vielen Dank für die Eingabe. Eigentlich hast du recht. Es scheint, als hätte ich die Nummer 1 im Buch "RESTful Java with Jax-rs" gelesen, aber etwas außerhalb des Kontexts. Aber ich erinnere mich sehr gut daran, dass ich das als Antwort auf eine der Fragen zum Stackoverflow selbst gelesen habe (glauben Sie mir, wenn ich sage, dass ich mich sehr bemühe, diesen Link zu finden, um es auch meinen Kollegen zu beweisen :)) und # 2 genau das war, was ich war Auf der Suche nach. Einige Rückmeldungen zum Design. Danke dir!
Shahshi15

PS: Ich bin mir nicht sicher, ob das Posten hier gegen die Regel verstößt, aber Sie können wahrscheinlich auch eine meiner anderen Fragen beleuchten? Bitte? :) stackoverflow.com/questions/20508008/…
shahshi15

Nur um Ihre Redundanzerklärung für zu klären /users/id/{id}, ermöglicht dies eine erweiterte Funktionalität und ermöglicht einfach den Zugriff auf eine Ressource über mehrere Bezeichner (ID, Guid, Name). auch hier
Daniel Dubovski

4
Meine Antwort wäre, dass der geeignete Weg, um beispielsweise auf einen bestimmten Benutzer zu verweisen, / users / {id} wäre. Wenn Sie Benutzer anhand einer bestimmten E-Mail-Adresse suchen möchten, die nicht die eindeutige Kennung für die Benutzer ist, die ich ausführen würde / users? Email = {email}, da dies eine Möglichkeit ist, die Sammlung von Benutzern zu filtern und nicht eine bestimmte Ressource anhand ihrer Ressource zu identifizieren Bezeichner als / users / {id} ist.
Kevin M

Gute Antwort! Daumen hoch dafür. Das einzige, was ich empfehlen würde, ist, Ihre API ein wenig zu ändern, da REST namenorientiert sein sollte, sodass Ihre Ressourcenzuordnungen ungefähr so ​​aussehen sollten: GET /user/1234und nichtGET /users/123
Sammy

36

Wenn Sie dies pragmatisch betrachten, haben Sie eine Sammlung von Benutzern:

/users   # this returns many

Jeder Benutzer hat einen dedizierten Ressourcenstandort:

/users/{id}    # this returns one

Sie haben auch eine Reihe von Möglichkeiten, nach Benutzern zu suchen:

/users?email={email}
/users?name=*bob*

Da dies alles Abfrageparameter für / Benutzer sind, sollten sie alle Listen zurückgeben. Auch wenn es sich um eine Liste von 1 handelt.

Ich habe hier einen Blog-Beitrag über pragmatisches RESTful-API-Design geschrieben, der unter anderem hier darüber spricht: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api


Danke für die Antwort vinay. Wenn wir dies jedoch aus einer anderen Perspektive betrachten, wird {email} genau wie {id} IMMER ein Ergebnis zurückgeben. Wenn wir wirklich suchen, warum nicht? Id = {id} genauso wie für E-Mails verwenden? Ich habe mich gefragt, ob es überhaupt konsequent sein soll. PS: Neu bei Stackoverflow, wusste nicht, dass ich nur eine Antwort geben kann. Aber danke für deine Antwort! Bin dankbar. Vielleicht können Sie mir auch bei diesem helfen: stackoverflow.com/questions/20508008/…
shahshi15

7
Hier kommt der "Design" -Aspekt des API-Designs ins Spiel. Ihre Ressource sollte einen dedizierten Speicherort haben. Wo ist der Ort? Ist der Ort nach ID? Wenn ja, dann "suchen" Sie nicht nach ID, sondern "erhalten" nach ID. Aber du suchst nach allem anderen. Natürlich gibt es hier keine feste Regel. Es ist nur eine Perspektive :)
Vinay Sahni

6
Ich würde auch argumentieren, dass Ihre API auf diese Weise stabiler ist. Sie wissen wirklich, dass Ihre ID eindeutig ist, sind sich aber über die E-Mail-Adresse wirklich sicher? Selbst wenn es eindeutig ist, ist es wahrscheinlich nicht dauerhaft, da der Benutzer es ändern kann. Also / users? Email = {email} macht deutlich, dass dies tatsächlich eine Abfrage ist und kein Zugriff auf eine Ressource mit einer Permament-ID.
Lex82

Ich glaube, das ist tatsächlich die richtigere Antwort. Das Filtern einer Sammlung nach E-Mail-Adresse kann auf Platzhaltern basieren, sodass nicht immer nur ein Ergebnis zurückgegeben wird.
Kevin M

@VinaySahni Was würden Sie über ein Muster wie: /user?by=email&email="abc@pqr.com "/ user? By = id & id =" xashkhx "/ users? FilterA =" a "& filterB =" b "(Plural) sagen für mehrere Benutzer)
Shasak

2

Informationen zu den Benutzerressourcen

Auf dem Pfad erhalten /usersSie immer eine Sammlung von zurückgegebenen Benutzerressourcen.

Auf dem Weg können /users/[user_id]Sie verschiedene Dinge erwarten:

  1. Sie sollten eine Singleton-Ressource erhalten, die die Benutzerressource mit ihrer Kennung [user_id] oder darstellt
  2. Eine 404- Antwort wurde nicht gefunden, wenn kein Benutzer mit der ID [Benutzer-ID] vorhanden ist oder
  3. ein verbotenes 401, wenn Sie nicht auf die angeforderte Benutzerressource zugreifen dürfen.

Jeder Singleton wird durch seinen Pfad und seine Kennung eindeutig identifiziert, und Sie verwenden diese, um die Ressource zu finden. Es ist nicht möglich, mehrere Pfade für den Singleton zu verwenden.

Sie können den Pfad /usersmit Abfrageparametern ( GETParametern) abfragen . Dadurch wird eine Sammlung mit Benutzern zurückgegeben, die die angeforderten Kriterien erfüllen. Die zurückgegebene Sammlung sollte die Benutzerressourcen enthalten, alle mit ihrem identifizierenden Ressourcenpfad in der Antwort.

Parameter können jedes Feld sein, das in den Ressourcen der Sammlung vorhanden ist. firstName, lastName,id

Über die E-Mail

Die E-Mail kann entweder eine Ressource oder eine Eigenschaft / ein Feld der Benutzerressource sein.

- E-Mail als Eigentum des Benutzers:

Wenn das Feld eine Eigenschaft des Benutzers ist, würde die Benutzerantwort ungefähr so ​​aussehen:

{ 
  id: 1,
  firstName: 'John'
  lastName: 'Doe'
  email: 'john.doe@example.com'
  ...
}

Dies bedeutet, dass es keinen speziellen Endpunkt für E-Mails gibt. Sie können einen Benutzer jetzt anhand seiner E-Mail-Adresse finden, indem Sie die folgende Anfrage senden : /users?email=john.doe@example.com. Welche (vorausgesetzt, E-Mails sind nur für Benutzer) eine Sammlung mit einem Benutzerelement zurückgeben, das mit der E-Mail übereinstimmt.

- E-Mail als Ressource:

Aber wenn E-Mails von Benutzern auch Ressourcen sind. Anschließend können Sie eine API /users/[user_id]/emailserstellen, in der eine Sammlung von E-Mail-Adressen für Benutzer mit ID zurückgegeben wird user_id. /users/[user_id]/emails/[email_id]Gibt die E-Mail des Benutzers mit user_id und ['email_id'] zurück. Was Sie als Bezeichner verwenden, liegt bei Ihnen, aber ich würde mich an eine ganze Zahl halten. Sie können eine E-Mail vom Benutzer löschen, indem Sie eine DELETEAnfrage an den Pfad senden , der die E-Mail identifiziert, die Sie löschen möchten. So löscht beispielsweise DELETEon /users/[user_id]/emails/[email_id]die E-Mail mit email_id, die dem Benutzer mit user_id gehört. Höchstwahrscheinlich darf nur dieser Benutzer diesen Löschvorgang ausführen. Andere Benutzer erhalten eine 401-Antwort.

Wenn ein Benutzer nur eine E-Mail-Adresse haben kann, können Sie sich daran halten. /users/[user_id]/email Dies gibt eine Singleton-Ressource zurück. Der Benutzer kann seine E-Mail-Adresse aktualisieren, indem er PUTdie E-Mail-Adresse unter dieser URL eingibt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.