2009-02-24 13 views
13

Nella mia continua ricerca per cercare di avvolgere la mia mente attorno a RESTful-ness, sono venuto in un altro posto dove non sono sicuro di come procedere. Ho creato un programma di sperimentazione per me stesso in cui avrei progettato un semplice sistema di voto per una risorsa, proprio come il modo in cui SO consente di votare sulle domande. Quindi, dire che la mia risorsa è un'immagine, e posso ottenere un'immagine da un ID, in questo modo:Come progetteresti un sistema di votazione RESTful?

http://www.mysite.com/images/123123 

e in questo esempio, che i rendimenti dire, una rappresentazione JSON di un'immagine, in questo modo:

{ 
"URL":"http://www.mysite.com/images/123123.jpg", 
"Rep":"100" 
} 

Come progettare un modo per "votare" su quell'immagine? Mi piacerebbe due operazioni; up-voto e down-vote. Il cliente non dovrebbe sapere quanto peso abbia ciascuno, perché mi piacerebbe che il premio per un voto in alto/basso fosse deciso a livello di server, così posso cambiarlo ogni volta che mi piace.

La mia prima idea era di avere qualcosa di simile:

http://www.mysite.com/vote/images?image=123123 

A questo URL, si potrebbe postare qualcosa di simile al seguente:

{ 
"Vote":"UpVote" 
} 

Ma sono diffidare di che - a me che dice RPC travestito. Sarebbe un modo scadente per progettare questo? Se sì, quali altri motivi posso provare?

risposta

7

Per essere riposante si dovrebbe restituire qualcosa di simile

{ 
"URL":"http://www.mysite.com/images/123123.jpg", 
"Rep":"100" 
"UpVoteLink":"http://blah, blah, blah", 
"DownVoteLink":"http://blah, blah, something else blah", 
} 

Per quanto riguarda il resto è interessato, non importa quello che il formato dei collegamenti sono. Finché il client sa che è necessario eseguire il POST su "UpVoteLink" o "DownVoteLink", non potrebbe importare di meno quale sia il formato dell'URL.

Inoltre, se decidi tra due settimane che non ti piacciono gli URL che hai scelto, puoi cambiarli e nessuno se ne preoccuperà!

Ok, ok, se si vuole veramente un suggerimento per un design url, come su

POST http://www.mysite.com/UpVotes?url=http://www.mysite.com/images/1234.jpg 

POST http://www.mysite.com/DownVotes?url=http://www.mysite.com/images/1234.jpg 

cosa è interessante di questo progetto è che si potrebbe votare sulle immagini che non sono nemmeno sul tuo sito!

+3

Hmm - Penso di aver capito, ma UpVoteLink non è un'azione, non una risorsa? Non potresti semplicemente avere un "VoteLink" e POST a quello, e in quella richiesta, specificare se è un upvote o un downvote? –

+1

Se pensi a un voto come a una risorsa allora "UpVotes" potrebbe essere la raccolta di voti di tipo up e la risorsa "DownVotes" è la raccolta di voti di tipo down. Forse avrei dovuto denominare i collegamenti UpVotesLink e DownVotesLink ma il nome del collegamento non influisce molto. –

+0

Ahh - interessante! Molto bello –

-3

Sembrerebbe sciocco a me ad inserire una risposta semplice come quello avvolto in JSON

Perché non qualcosa di semplice come questo, si potrebbe farlo in una chiamata AJAX per rendere più uber bello ..

Una richiesta GET formattato come segue

http://www.mysite.com/vote.php?image=123&vote=up 

o POST (questo esempio utilizzando jQuery)

$.post("http://www.mysite.com/vote.php", {image:"123", vote:"up"}); 

(Supponendo PHP, ma qualunque cosa si applica)

+4

Molto male. Non consentire mai all'utente di eseguire azioni "distruttive" utilizzando GET requrest. Cosa succede se Google ottiene questo URL e inizierà a colpirlo a 500 Hz? –

+0

Anche se penso che i problemi di sicurezza non facciano parte della domanda discussa qui: Se si limita la richiesta GET agli utenti autorizzati, questo non dovrebbe essere un grosso problema. – Javier

+0

Ma è un aggiornamento - è chiaramente un PUT nel migliore dei casi, o POST nel peggiore dei casi. Non è mai possibile utilizzare un GET per modificare i dati, anche se autorizzati. Semplicemente non ha senso. –

0

Se stai lavorando con Rails, mi piacerebbe andare per questo get-URL:

http://www.mysite.com/images/123123/up_vote 

e

http://www.mysite.com/images/123123/down_vote 

1. Definisci le azioni "up_vote" e "down_vote" nel controller Immagini e fai in modo che aumenti o diminuisca il valore di voto dell'oggetto-modello-immagine.

2. Impostare il seguente percorso in config/routes.rb:

map.resources :images, :member => { :up_vote => :get, :down_vote => :get } 

... e il gioco è fatto (più o meno ;-)).

+0

È RESTful, però? La mia comprensione era che non dovresti esporre le azioni agli utenti in un URI, solo risorse. Inoltre, non renderebbe GET un'operazione non sicura? –

+0

Come Anton Gogolev ha commentato ad un'altra risposta: Sì, in teoria, rende GET un'operazione non sicura. Ma IMHO lo stesso tipo di danno potrebbe essere fatto se si utilizza una richiesta POST e per me sembra più una richiesta GET. – Javier

+0

Bene, GET/POST a parte, non è ancora un-RESTful per esporre un'azione attraverso un URL? –

3

Le API REST dovrebbero rappresentare nomi, quindi penso che tu abbia la prima parte corretta: una singola immagine è rappresentata da un singolo URL (ad esempio http://www.mysite.com/images/123123). Non sono sicuro di virare su e /down_vote is la strada da percorrere però.

http://www.mysite.com/images/123123è l'oggetto e si desidera modificare che, non qualche altro URL (a meno che non si stavano facendo http://www.mysite.com/votes/images/123123). Penso che dovresti solo pubblicare su http://www.mysite.com/images/123123. Questo rende le richieste GET intrinsecamente non distruttive poiché recupera l'immagine, mantiene un design RESTful e mantiene i tuoi URL puliti.

+0

... cosa succede se consenti agli utenti di caricare/gestire quelle immagini? in questo caso non vuoi limitarti usando il POST per fare voti su un'immagine. linea di fondo: tutto dipende dai casi d'uso attorno all'applicazione immagine. – Javier

+0

Se gli utenti dovessero caricare immagini, penserei che vorresti che POST i dati vengano pubblicati su http://www.mysite.com/images/. In tal caso,/images è la raccolta di immagini che vorresti aggiungere alla raccolta. –

4

In termini di risorse, un'immagine è una cosa che ha un URI (che è ciò che lo rende una risorsa). Oltre a ciò, ha un sacco di proprietà (dimensioni, dati EXIF, ecc.).

Quando pensi ai voti per un'immagine, domanda se i voti sono una risorsa in se stessi.

Le probabilità sono: fare un GET su/immagini/23/voti restituirebbe un sommario o l'elenco di tutti i voti che l'interfaccia utente userebbe per visualizzare accanto all'immagine. Ogni volta che vuoi cambiare quei voti, la risorsa che stai cambiando è il voto.

Per essere tranquilli, il client deve solo comprendere il tipo di supporto che hai progettato, non gli URI o il processo da seguire per votare.

Nel tuo esempio, definiresti un nuovo formato utilizzato ovunque sul tuo sito. Per riformulare yoru esempio, un Get/immagini/23/voti sarebbero tornati (in xml ma si può riformulare in JSON):

<votes> 
<link href="/images/23" rel="subject" /> 
<form action="/images/23/votes" mediatype="application/json"> 
    <submit name="Vote" value="Up">Vote up</submit> 
    <submit name="Vote" value="Down">Vote down</submit> 
</form> 
</votes> 

L'idea alla base di questo formato è che avete un modo universale per definire come il il client invia i dati al server e crea il documento. Tutti gli esami precedenti che sono stati visualizzati correttamente rendono l'URI dipendente dal server. Propongo che ciò che si invia al server debba essere definito nei moduli inviati dal server.

Quindi dedica più tempo a definire come yoru json client comprenderà come creare oggetti json per l'invio in base a un linguaggio generico, e scoprirai che una volta fatto questo, hai un accoppiamento molto basso tra cient e server, e il server ha la flessibilità di cambiare tutte le specifiche senza rompere i client.

Problemi correlati