2014-10-19 16 views
12

Per quanto ne so, quattro tipi di metodi sono utilizzati in RESTful API:RESTful API quando più azioni sullo stesso URI

GET per ottenere la risorsa.
POST per l'aggiornamento della risorsa.
PUT per la creazione o la sostituzione della risorsa.
DELETE per l'eliminazione della risorsa.

Supponiamo di disporre di una risorsa denominata apple e possiamo "aggiornarla" in diversi modi. Ad esempio, sbucciarlo, affettarlo o renderlo succo di mela.
Ciascuna di queste tre diverse azioni di aggiornamento prende argomenti diversi, e di loro API, la parte comune sarà:

POST /apple HTTP/1.1 
Host: www.example.com 

<different combination of arguments> 

In questa situazione, tre API condividono lo stesso URI e lo stesso metodo di richiesta, le uniche differenze di loro sono argomenti. Penso che questo costringa il backend ad essere pronto ad accettare la serie di union di questi argomenti, e per distinguere quale azione sia effettivamente richiesta, il back-end deve verificare la combinazione degli argomenti. È molto complicato e non elegante.

Quindi la mia domanda è:
In questi casi di apple, come elaborare un elegante set di API RESTful che rendono il backend facilmente gestibile con esso.

risposta

8

Prima di tutto, cercare di evitare di confondere i metodi HTTP con le operazioni CRUD. Credo che sia la principale fonte di confusione in REST. I metodi HTTP non si traducono in operazioni CRUD in modo pulito come quello. Ho una risposta dettagliata qui:

S3 REST API and POST method

In breve.

  • POST è il metodo utilizzato per qualsiasi operazione che non è standardizzata da HTTP e sottopone il carico utile all'URI di destinazione.
  • PUT viene utilizzato per sostituire completamente la risorsa al presente URI e sottopone il carico utile al servizio stesso.
  • PATCH è per aggiornamenti idempotenti parziali, con una differenza tra lo stato corrente e quello desiderato.
  • DELETE viene utilizzato per eliminare la risorsa.
  • GET viene utilizzato per recuperare la risorsa.

Ora, sul lato backend, prova a pensare alle risorse REST più come una macchina a stati in cui è possibile utilizzare i metodi per forzare una transizione piuttosto che un oggetto con metodi. In questo modo focalizzi l'implementazione sulla risorsa stessa, non sull'interazione con il protocollo. Ad esempio, è possibile modificare direttamente gli attributi di un oggetto dal carico utile del metodo e quindi disporre di un metodo chiamato per rilevare la transizione necessaria.

Ad esempio, si può pensare a una mela come a tre stati, intera, affettata, affettata e spremuta. Transizione tra stati utilizzando il comportamento standardizzato dei metodi.

Per esempio:

GET /apple 

{"state": "whole", 
"self": "/apple"} 

poi si desidera affettarlo. Si può fare qualcosa di simile:

PUT /apple 

{"state": "sliced"} 

Oppure si può fare qualcosa di simile:

PATCH /apple 

{"from_state": "whole", "to_state": "sliced"} 

O anche qualcosa di simile:

POST /apple 

{"transition": "slice"} 

L'idea è che le implementazioni possono essere sufficiente che generici non devi preoccuparti troppo dell'abbinamento della risorsa ai metodi HTTP.

  • La versione PUT è idempotente, quindi i client possono scegliere di usarlo quando hanno bisogno di idempotence.
  • La versione PATCH garantisce che il client conosca lo stato corrente e stia tentando una transizione valida.
  • La versione POST è la più flessibile, puoi fare tutto ciò che vuoi, ma deve essere documentato in dettaglio. Non puoi semplicemente supporre che i tuoi clienti sapranno come funziona il metodo.

Finché l'implementazione della risorsa capisce che quando apple.state viene modificato in qualche altra cosa che dovrebbe rilevare ciò che è avvenuto il cambiamento e di eseguire la transizione adeguata, si sono completamente disaccoppiati dal protocollo. Non importa quale metodo è stato usato.

Credo che questa sia la soluzione più elegante e rende tutto più facile da gestire dal lato back-end. Puoi implementare i tuoi oggetti senza preoccuparti troppo del protocollo. Finché gli oggetti possono essere trasferiti tra stati, possono essere utilizzati da qualsiasi protocollo in grado di effettuare tali transizioni.

+0

'PUT/apple/color newColor = red', o' PUT/apple cmd = updateColor & newColor = red', si concentra sulla combinazione di uri e argomenti di queste due API, quale è migliore (o più RESTful)? – dastan

+3

Nessuno dei due è RESTful. Il primo richiederebbe che l'intero carico utile fosse la rappresentazione di una risorsa di colore. Il secondo implica il comando updateColor che viene eseguito dalla risorsa apple stessa. Posso vedere 'PUT/apple/color' essere RESTful se 'red' è l'intero payload con il tipo di media dell'attributo apple.color, ma la seconda opzione è irreparabile. –

0

Penso che questo dipenda dall'implementatore, ma vedo due approcci. A rigor di una prospettiva di responsabilità singola, potrebbe essere opportuno fornire servizi separati per queste distinte operazioni.

Tuttavia, se si insiste su un singolo servizio, suppongo che sia possibile passare un oggetto con un qualificatore del tipo di azione per semplificare la delega della richiesta a un codice diverso nel servizio. Il singolo oggetto può quindi avere altri parametri opzionali per supportare le esigenze di dati di ciascuna operazione.

1

Pensare in termini di risorse. Qui Apple è una risorsa.

Per aggiungere una o più mele alla lista "/ mele", utilizzare POST. Lo stile REST consente di pubblicare array.

POST /apples HTTP/1.1 
Host: www.example.com 

Ora si supponga di avere una mela con ID 123. È possibile ottenere informazioni utilizzando il metodo GET on "/ mela/123".

GET /apples/123 HTTP/1.1 
Host: www.example.com 

Per apportare qualsiasi modifica a 123 Apple, basta POST direttamente.

PUT /apples/123 HTTP/1.1 
Host: www.example.com 

Pare che, fetta, o renderlo succo di mela - tutti questi sono fondamentalmente cambiando alcuni attributi di mela 123. Come dicevi (giustamente), METTERE diversa combinazione di attributi.

+0

POST per l'aggiornamento? Questo è assolutamente sbagliato. –

+0

Oh tu correggi. Ho corretto a mettere. Grazie. – Jangid

+6

@DavidBrabant non è "semplicemente sbagliato" utilizzare POST per l'aggiornamento. Il POST può essere usato per qualsiasi operazione che non sia standardizzata con altri metodi. PUT deve essere un aggiornamento idempotente, quindi se si desidera avere un aggiornamento non idempotente, il POST è il metodo corretto da utilizzare. –

5

La mia API HTTP RESTful è piuttosto diversa dalla tua. Ho:

GET per ottenere una risorsa.
POST per aggiungere una nuova risorsa a una raccolta.
PUT per sostituire una risorsa (incluse le raccolte troncate).
DELETE per l'eliminazione di una risorsa.
PATCH per l'aggiornamento di una risorsa.
LINK per indicare una relazione tra due risorse.
UNLINK per la rimozione di una relazione tra due risorse.

Una risorsa 'foglia' può essere pensata anche come una collezione.

Per esempio, supponiamo di avere /fruits e si POST un apple a quella risorsa raccolta, che restituisce

201 Created 
Location: /fruits/apple 

Allo stesso modo, è possibile trattare /fruits/apple come una raccolta delle sue proprietà, in modo da:

GET /fruits/apple 
-> 
colour=red&diameter=47mm 

GET /fruits/apple/colour 
-> 
red 

GET /fruits/apple/diameter 
-> 
47mm 

e quindi:

PUT /fruits/apple/slices 
"12" 
-> 
201 Created 

GET /fruits/apple 
-> 
colour=red&diameter=47mm&slices=12 

Quindi, in sintesi, consiglierei di rappresentare le azioni come nomi e di individuare quei nomi come risorse secondarie della risorsa a cui si desidera applicare l'azione.

Problemi correlati