2013-03-06 10 views
18

Sono nuovo nello sviluppo web lato server e di recente ho letto molto sull'implementazione delle API RESTful. Un aspetto dell'API REST su cui sono ancora bloccato è il modo di strutturare la gerarchia URI che identifica le risorse con cui il client può interagire. In particolare, sono bloccato nel decidere in che modo fare la gerarchia e cosa fare nel caso in cui le risorse siano composte da altri tipi di risorse.Come strutturare la gerarchia delle risorse REST?

Ecco un esempio che si spera mostrerà cosa intendo. Immagina di avere un servizio web che consente agli utenti di acquistare prodotti da altri utenti. Quindi, in questo semplice caso, ci sono due risorse di livello superiore utenti e prodotti. Ecco come ho cominciato a strutturare la gerarchia URI,

Per gli utenti:

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

Per i prodotti:

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

In entrambi i casi gli oggetti in ogni riferimento gerarchia di un sottoinsieme degli oggetti nell'altra gerarchia. Ad esempio /users/{id}/bought è un elenco dei prodotti acquistati da un utente, che è un sottoinsieme di /products. Inoltre, /products/{id}/seller fa riferimento all'utente che ha venduto un prodotto specifico.

Poiché questi URI fanno riferimento ad altri oggetti o sottoinsiemi di altri oggetti, l'API deve supportare cose come questa: /users/{id}/bought/id/description e /products/{id}/buyer/location? Perché se quei tipi di URI sono supportati, cosa si può fermare qualcosa come questo /users/{id}/bought/{id}/buyer/bought/{id}/seller/name o qualcosa di altrettanto contorto? Inoltre, in questo caso, come gestireste il routing poiché il router nel server dovrebbe interpretare gli URI di lunghezza arbitraria?

risposta

22

L'obiettivo è quello di creare identificatori di risorse convenienti, non provare a fare riferimenti incrociati a tutto. Non è necessario ripetere le vostre relazioni di database in rappresentanza URL :) non dovrebbero mai esistere

link come /product/{id}/buyer, perché c'è già è identificativo per quella risorsa: /user/{id}

Anche se è ok per avere /product/{id}/buyers-list perché elenco di acquirenti è una proprietà del prodotto che non esiste in altri contesti.

+0

Quindi, quello che stai dicendo è che ogni risorsa nel sistema ha esattamente ** ** un URI? Perché questo rende tutto molto più semplice. Nell'esempio sopra, cosa consiglieresti se volessi esporre il venditore di alcuni prodotti tramite l'API (i prodotti hanno solo un venditore)? Dovrei semplicemente fare in modo che le persone facciano * GET/products/{id} * che restituirebbe qualche oggetto JSON con il venditore al suo interno? – martega

+2

JSON per '/ products/{id}' può contenere oggetti utente nidificati per comodità o url per quell'utente, è una tua scelta e non cambia il fatto che entrambi esistono separatamente. – Anri

+3

btw, aiuta a guardare le API di altri servizi. Ad esempio: https://developer.foursquare.com/docs/venues/venues – Anri

11

Si dovrebbe pensare in modo CRUD, in cui ogni entità supporta Crea, Leggi, Aggiorna ed Elimina (in genere utilizzando i verbi HTTP GET, POST, PUT e DELETE rispettivamente).

Ciò significa che i punti finali di solito raggiungono un livello solo profondo. Per esempio

Utenti

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 

entrare in maggiori dettagli, come ad esempio /users/:id/about non è probabile necessario. Anche se potrebbe funzionare, potrebbe essere leggermente più specifico.

Forse nel tuo caso si potrebbe aggiungere in:

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

dove si poteva restituire un elenco di id (che può essere recuperato attraverso i prodotti API), oppure si potrebbe popolare i prodotti prima di mandarli indietro se desideri.Se si sceglie di popolarli, probabilmente non si dovrebbe quindi popolare gli utenti a cui fa riferimento ciascun prodotto. Ciò porterà a includere circolari ed è sbagliato.

e per i prodotti, nella vostra sitation vorrei utilizzare:

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