2013-03-06 12 views
18

Ich bin neu auf der Server-Seite Web-Entwicklung und vor kurzem habe ich viel über die Implementierung von RESTful APIs gelesen. Ein Aspekt der REST-APIs, an denen ich immer noch festhalte, ist die Strukturierung der URI-Hierarchie, die Ressourcen identifiziert, mit denen der Client interagieren kann. Insbesondere muss ich entscheiden, wie detailliert die Hierarchie erstellt werden soll und was zu tun ist, wenn Ressourcen aus anderen Ressourcentypen bestehen.Wie strukturiert man die REST-Ressourcenhierarchie?

Hier ist ein Beispiel, das hoffentlich zeigen wird, was ich meine. Stellen Sie sich vor, wir haben einen Webservice, mit dem Nutzer Produkte von anderen Nutzern kaufen können. Also in diesem einfachen Fall gibt es zwei Top-Level-Ressourcen Benutzer und Produkte. Hier ist, wie ich begann, die URI-Hierarchie zu strukturieren,

Für Benutzer:

/users 
     /{id} 
      /location 
      /about 
      /name 
      /seller_rating 
      /bought 
      /sold 

Für Produkte:

/products 
     /{id} 
       /name 
       /category 
       /description 
       /keywords 
       /buyer 
       /seller 

In beiden Fällen Objekte in jeder Hierarchie Referenz eine Teilmenge der Objekte in der anderen Hierarchie. Zum Beispiel ist /users/{id}/bought eine Liste der Produkte, die ein Benutzer gekauft hat, was eine Untermenge von /products ist. Außerdem bezieht sich /products/{id}/seller auf den Benutzer, der ein bestimmtes Produkt verkauft hat.

Da diese URIs auf andere Objekte oder Teilmengen anderer Objekte verweisen, sollte die API Folgendes unterstützen: /users/{id}/bought/id/description und /products/{id}/buyer/location? Weil, wenn diese Arten von URIs unterstützt werden, was etwas wie dieses /users/{id}/bought/{id}/buyer/bought/{id}/seller/name, oder etwas ähnlich gewundenes zu stoppen ist? Wie würden Sie in diesem Fall auch mit dem Routing verfahren, da der Router im Server URIs beliebiger Länge interpretieren müsste?

Antwort

22

Das Ziel ist es, bequeme Ressourcen-IDs zu erstellen, versuchen Sie nicht, alles zu referenzieren. Sie müssen nicht Ihre Datenbank Beziehungen in URL Darstellung wiederholen :)

Links wie /product/{id}/buyer sollte es nie geben, denn es gibt bereits Kennung für diese Ressource ist: /user/{id}

Obwohl es in Ordnung ist /product/{id}/buyers-list zu haben, weil die Liste der Käufer ist eine Produkteigenschaft, die in anderen Kontexten nicht existiert.

+0

Also, was Sie sagen, ist, dass jede Ressource im System genau einen hat ** ** URI? Weil das alles viel einfacher macht. Was würden Sie im obigen Beispiel empfehlen, wenn ich den Verkäufer eines Produkts über die API anzeigen möchte (Produkte haben nur einen Verkäufer)? Soll ich Leute dazu bringen, * GET/products/{id} * zu machen, die ein JSON-Objekt mit dem Verkäufer zurückgeben? – martega

+2

JSON für '/ products/{id}' kann verschachteltes Benutzerobjekt für Ihre Bequemlichkeit oder URL zu diesem Benutzer enthalten, es ist Ihre Wahl und es ändert nicht die Tatsache, dass beide getrennt existieren. – Anri

+3

BTW, hilft es, die APIs anderer Dienste zu betrachten. Zum Beispiel: https://developer.foursquare.com/docs/venues/venues – Anri

11

Sie sollten es in einer CRUD-Weise denken, in der jede Entität Create, Read, Update und Delete unterstützt (normalerweise mit den HTTP-Verben GET, POST, PUT und DELETE).

Dies bedeutet, dass Ihre Endpunkte normalerweise nur eine Ebene tief gehen. Zum Beispiel

Benutzer

GET /users  - Return a list of all users (you may not want to make this publically available) 
GET /users/:id - Return the user with that id 
POST /users  - Create a new user. Return a 201 Status Code and the newly created id (if you want) 
PUT /users/:id - Update the user with that id 
DELETE /users/:id - Delete the user with that id 

gehen mehr ins Detail, wie /users/:id/about ist wahrscheinlich nicht erforderlich. Auch wenn es funktionieren mag, kann es leicht überspannt werden.

Vielleicht in Ihrem Fall könnten Sie hinzufügen, in:

GET /users/:id/bought - Array of products that the user bought 
GET /users/:id/sold - Array of products that the user sold 

, wo Sie eine Liste von IDs zurückkehren konnte (die durch die Produkte API abgerufen werden können), oder Sie können die Produkte füllen, bevor sie zurück zu senden, wenn du wünschst.Wenn Sie sich dafür entscheiden, diese zu füllen, sollten Sie wahrscheinlich nicht die Benutzer auffüllen, auf die von jedem Produkt verwiesen wird. Dies führt zu zirkulären Einschlüssen und ist falsch.

Und für Produkte, würde ich in Ihrem sitation verwenden:

GET /products- Return a list of all products 
GET /products/:id - Return the products with that id 
POST /products- Create a new product. Return a 201 Status Code and the newly created id (if you want) 
PUT /products/:id - Update the product with that id 
DELETE /products/:id - Delete the product with that id 

GET /products/:id/buyers  - Array of who bought the product 
GET /products/:id/sellers - Array of everyone selling the product