2011-07-03 15 views
5

Sto esponendo una API REST, ed è incredibilmente facile e veloce da utilizzare finché si esegue CRUD (Crea, Aggiorna, Elimina). Ma ho questo Ticket che restituisce una lista di biglietti (get), un Ticket/{id} che ottiene un oggetto particolare (get) e un metodo di attivazione (put) che cambia lo stato del ticket da non attivato ad attivato.Qual è la cosa migliore da fare quando hai bisogno di un verbo usando REST API?

Ora ho bisogno di dare al "consumatore" REST la possibilità di fare qualcosa di simile (in ws si chiamerà: GetAndActivateRandomTicket() e mi chiedo, cosa dovrebbe essere descritto come su REST? post? a put? a get ?. L'obiettivo è ottenere una quantità casuale di ticket e impostare lo stato su attivo. Qualcosa come un get & messo allo stesso tempo ma senza conoscere prima mano il {id} per il put.

Dovrebbe essere/biglietti? attivare = true & quantità = 5? Cosa verbo? Devo esporre un verbo al posto di un sostantivo? qual è il 'migliori pratiche' su questo tema?

Grazie.

risposta

1

ho estratto questo:

Tutto può essere fatta una risorsa incluse le operazioni, sessioni e altri tali entità non di dominio :)

e andò con:

risorsa TicketActivation.

[POST] con un parametro di query di importo restituirà un insieme di ticket casuali attivati. e restituisci l'url della risorsa come tale che puoi ottenere come/ticket/id = 1,2,3,4,5 [GET] restituirà i biglietti normalmente con un filtro opzionale di id per restituire più ticket [PUT] userà anche il filtro di id e imposterà l'attivazione true o false a seconda del parametro.

così posso fare:

[post] 
/ticket/activation/?amount=5 

risorsa restituito sarà qualcosa di simile a/biglietti id = 1,2,3,4,5 così posso emettere un ottenere su di esso?.

[get] 
/ticket?id=1,2,3,4,5 

[put] 
/ticket/activation?id=1,2,3,4,5&deActivate [OR] 
/ticket/activation?id=1,2,3,4,5&activate 

Credo che questo è la soluzione più elegante e anche riposante e chiaro a questo problema, ho voluto condividere per riferimento futuro. Inoltre, se pensi che ci sia un problema con questo approccio, sentiti libero di commentarlo.

3

Alcune risorse sono facilmente identificabili ed esistono nel dominio. Alcuni però sono un po 'complicati, come hai sottolineato. Ma il ROA (architettura orientata alle risorse) richiede un po 'di tempo per abituarsi. Qualsiasi cosa può essere costituita da una risorsa, incluse transazioni, sessioni e altre entità non di dominio :)

Nel tuo caso sembra che tu abbia una risorsa 'algoritmica' - selezionando una quantità casuale di ticket e attivandoli. Sono sicuro che questa "casualità" abbia un modo di selezionare i biglietti che non è puramente casuale, altrimenti ci sarà uno spreco di calcoli con l'ottenimento di un set di biglietti già attivato.

Quindi non sono sicuro di come si sta verificando l'attivazione: qualcuno seleziona l'attivazione rispetto a un gruppo di ticket (caselle di controllo) o parte del "pacchetto dati" senza intervento umano?

È descrizione sembra accennare quest'ultimo - così una buona pratica è quella di fare ciò che hai appena detto: più opzioni sul URL:?

  • /Biglietti amountToActivate = 5; attivare (Si noti il ​​punto e virgola e solo la 'parola' attivare)
  • /Biglietti amountToActivate = 5 & activate = true (Nota:? personalmente ritengo quanto sopra è meglio da quando = true è in realtà ridondante, è un artefatto di URI non riposante dove la maggior parte gente dichiarerebbe esplicitamente = true - è buono come solo scrivere 'activate' nell'URL (implica true) ab sence implicherebbe falsa :)

tua risorsa è algoritmica e il 'consumatore del URL' umano quando la lettura avrebbe capito immediatamente l'ex URL, = true potrebbero non essere ben compreso, ma questo è solo me, forse . Vi è la tendenza a utilizzare anche quest'ultima poiché la maggior parte dei framework è in grado di analizzare i parametri di query e divisa per "&" e i punti e virgola potrebbero richiedere solo un lavoro

Nel caso in cui vi sia un intervento manuale, è possibile suddividerlo in due parti:

  • RICHIEDI:/Biglietti?fetchRandomAmountOfTickets = 100 (dal momento che è algoritmica)
  • PUT:/Biglietti (l' 'aggiornamento' parte del PUT per la lista dei biglietti che si 'Si' al di sopra di attivazione)

Spero che questo aiuti :)

+0

L'attivazione può avvenire in entrambi i modi, in un modo richiedendo i ticket e quindi attivando 1 o più. Questo è chiaro L'altro modo è che il consumatore vuole attivare qualsiasi biglietto disponibile (il casuale non è in realtà casuale ma un "SELECT ticket FROM Db LIMIT 1") è solo un biglietto. Quindi penso che la risposta sarebbe:/Ticket? AmountToActivate = 5 & activate = true (la mia preferenza personale) ma con quale verbo? OTTENERE? METTERE? INVIARE? Se l'attivazione è implicita nell'URL, penso che sia un GET, ma ciò va contro REST perché in realtà modifica qualcosa e non è lo spirito di GET .... 'ancora confuso' –

+0

Aaah! Io vedo. La confusione è con la modifica della risorsa con la chiamata "GET" - punto valido. L'ho trascurato. Ecco cosa puoi fare per rimanere fedele allo spirito di Rest :) GET:/Tickets/fetchAmountOfTickets = 100 & activated = false (o ... 100; notActivated) e quindi inviare una richiesta PUT con l'aggiornamento di attivazione. Non vedo il problema con questo. Stai filtrando GET w.r.t.alcuni parametri (algoritmici) e quindi la modifica di tali risorse utilizzando il client PUT – PhD

+0

potrebbe voler evitare get/put e fare entrambi con una singola richiesta semplicemente inviarmi i dati del ticket e impostare su attivato ... :) (senza sapere prima mano quale sarebbe stato attivato e restituito). –

2

Prima di tutto, GET dovrebbe essere idempotente e non apportare mai modifiche alla risorsa. L'attivazione di una risorsa dovrebbe essere eseguita utilizzando un PUT.

Quello che vorrei fare è creare un URL di risorsa come/Tickets/Random che come risultato di un GET restituisce un HTTP 303 per reindirizzare l'utente a un URL di risorsa reale determinato in modo casuale come/Tickets/12345. L'utente può quindi attivare questo ticket utilizzando un PUT. Tutto ciò che l'app utente deve sapere è/Tickets/URL casuale e può continuare ad attivare i ticket finché ce ne sono.

+0

PUT dovrebbe anche essere idempotente! Se PUT due volte, dovresti ottenere lo stesso risultato (ad esempio, reindirizza sempre lo stesso utente alla stessa risorsa casuale). Preferisco modellare i commit non idempotenti come POST. –

+0

Il PUT non reindirizza, il GET lo fa. Ed è idempotente perché reindirizza sempre, anche se non sempre alla stessa risorsa, e non apporta modifiche alla risorsa in questione. Secondo la tua definizione puoi usare solo un 303 con un POST mentre è normalmente usato con un GET. – Maurice

+1

GET non dovrebbe cambiare lo stato (significativamente); PUT imposta lo stato, ma ripeterlo due volte di seguito dovrebbe comportare la stessa cosa generale che si verificava una volta eseguita. I POST, essendo non idempotenti, possono cambiare lo stato nel modo che preferiscono. I reindirizzamenti non cambiano lo stato di per se stessi. –

4

Se ripetere l'operazione fa qualcosa di diverso (ad esempio, attiva un altro ticket), è non idempotente. Operazioni non idempotenti sempre mappa su POST (o un verbo personalizzato) in un'architettura RESTful.

Problemi correlati