2014-12-14 6 views
7

Si consideri un metodo API Web che non ha effetti collaterali, ma che prende come dati i dati binari. Un esempio potrebbe essere un metodo che indica all'utente se la loro immagine è photoshoppata o meno, ma non memorizza in modo permanente l'immagine o il risultato sui suoi server.Metodo di richiesta HTTP corretto per azione nullipotent che richiede dati binari

Un tale metodo deve essere un GET o un POST?

GET non sembra avere un modo consigliato di inviare dati al di fuori dei parametri URL, ma il comportamento del metodo implica un GET, che secondo le specifiche HTTP è per le risposte sicure, senza stato. Questo diventa particolarmente vincolante nella semantica di REST, il che implica che i metodi POST creano un nuovo oggetto sul server.

risposta

4

Questo diventa particolarmente vincolante nella semantica di REST, il che implica che i metodi POST creano un nuovo oggetto sul server.

Mentre una richiesta POST significa che l'entità inviato sarà trattato "come un nuovo subordinato della risorsa identificata dal Request-URI", non v'è alcun obbligo che questo risultato la creazione di un nuovo permanente oggetto o che qualsiasi nuovo oggetto di questo tipo sia identificato da un URI (quindi nessun nuovo oggetto fino a che il client lo sa). Un oggetto può essere transitorio, rappresentando i risultati di ad es. "Fornire un blocco di dati, come il risultato dell'invio di un modulo, a un processo di gestione dei dati" e non persistente dopo che l'entità che rappresenta quell'oggetto è stata inviata.

Anche se questo significa che un POSTpuò creare una nuova risorsa, ed è certamente il modo migliore per farlo quando è il server che darà quella nuova risorsa propria URI (con PUT è il metodo più appropriato, quando il il client detta il nuovo URI) può essere utilizzato anche per i casi che cancellano oggetti (anche se ancora una volta è una cancellazione di una singola risorsa identificabile da un URI, quindi DELETE è molto più appropriato), entrambi creano ed eliminano oggetti, cambiano più oggetti , può significare che la luce della tua cucina si accende ma che la risposta è la stessa sia che funzioni o che non sia andata a buon fine perché la comunicazione dal web server alla luce della cucina non consente di ottenere feedback sul successo. Può davvero fare qualsiasi cosa.

Ma, il tuo istinto sono buone nel voler che si tratta un GET: Mentre la scioltezza di POST significa che possiamo fare un caso per lui per quasi ogni richiesta (come fatto da approcci che utilizzano HTTP per un protocollo RPC-like , trattando essenzialmente HTTP come se fosse un protocollo di trasporto), questo è inelegante in teoria, inefficiente nella pratica e maldestro nella definizione. Hai una funzione idempotente che dipende esclusivamente da ciò a cui il cliente è interessato e che mappa più ovviamente lo GET in alcuni modi.

Se potessimo inserire tutto in un URI, allora GET sarebbe facile. Ad esempio possiamo definire una semplice aggiunta di interi con qualcosa come http://example.net/addInts?x=1;y=2 che rappresenta l'aggiunta di 71 e 2 e quindi essere una risorsa permanente immutabile che rappresenta il numero 3 (poiché i risultati di GET possono variare con le modifiche a una risorsa nel tempo, ma questa risorsa mai modifiche) e quindi utilizzare un meccanismo come HTML <form> o javascript per consentire al server di informare il client su come costruire gli URI per altri numeri (per mantenere i vincoli HATEOS e/o COD). Semplici!

Il tuo problema qui è che non hai input che possa essere rappresentato in modo conciso come i numeri 1 e 2 possono sopra. In teoria potresti fare qualcosa come http://example.net/photoshoppedCheck?image=data:image/png;base64,iVBORw0KGgoAAAANSU… e quindi creare un URI che rappresenti la risorsa dei risultati del controllo. Questo URI avrà però 4 caratteri per ogni 3 byte nell'immagine. Sebbene non ci sia un limite assoluto sulla lunghezza dell'URI, sia la teoria che la pratica consentono a questo di fallire (in teoria l'HTTP consente ai proxy e ai server di impostare un limite sulla lunghezza dell'URI, e in pratica lo fanno).

Un argomento può essere utilizzato per l'utilizzo di GET e l'invio di un corpo di richiesta nello stesso modo in cui si farebbe con un POST, e alcuni server Web vi permetteranno anche di farlo. Tuttavia, GET viene definito come restituisce un'entità che descrive la risorsa identificata nell'URI con intestazioni che limitano il modo in cui quell'entità esegue quella che descrive: Dal momento che il corpo della richiesta non fa parte di tale definizione, lo deve essere ignorato dal proprio codice! Se sei stato tentato di piegare questa regola, devi considerare che:

  1. Alcuni server Web rifiuteranno la richiesta o elimineranno il corpo, quindi potresti non essere in grado di farlo.
  2. Se il server web lo consente, il fatto che non sia specificato significa che non si può essere certi che un aggiornamento non "risolverà" questo e quindi interromperà il codice.
  3. Alcuni proxy rifiuteranno o elimineranno la richiesta.
  4. Alcune librerie client si rifiuteranno sicuramente di consentire agli sviluppatori di inviare un corpo di richiesta insieme a GET.

Quindi è un no-no sia nella teoria che nella pratica.

L'unico altro approccio che potremmo fare a parte POST è di avere un URI che consideriamo come rappresentazione di un'immagine che non è stata photoshoppata. Quindi se si GET si ottiene un'entità che descrive l'immagine (ovviamente potrebbe essere l'immagine reale, sebbene potrebbe anche essere qualcos'altro se estendiamo il concetto di negoziazione del contenuto) e quindi PUT controllerà l'immagine e se è considerata non è photoshoppato risponde con la stessa immagine e un o solo un 204 mentre se si ritiene che sia photoshopped risponde con un 400 perché abbiamo provato a PUT un'immagine photoshopped come una risorsa che può essere solo un non photoshoppato Immagine. Perché rispondiamo immediatamente, non c'è condizione di gara con richieste simultanee.

Francamente, questo sarebbe dannatamente giusto orribile. Anche se penso di aver trovato un caso per la lettera delle specifiche, è semplicemente disgustoso: REST ha lo scopo di aiutarci a progettare API chiare, non API ottiche che possiamo offrire a un troppo intelligente per il suo bene giustificazione di

No, in tutto il modo per andare qui è a POST l'immagine a un URI fisso che restituisce quindi una semplice entità che descrive l'analisi.

è perfettamente giustificabile come REST (il POST crea un oggetto transitoria sulla base di tale immagine, e poi risponde con un soggetto che descrive l'oggetto, e quindi l'oggetto scompare di nuovo). È semplice. È efficiente quanto potrebbe essere (non possiamo fare alcun caching HTTP † ma la maggior parte del ritardo di rete sarà sul caricamento piuttosto che il download in ogni caso). Si adatta anche al caso d'uso generale di "elaborare qualcosa" che è stato inventato per lo POST. (Ricorda che prima c'era HTTP, quindi REST ha descritto perché ha funzionato così bene, e quindi HTTP è stato perfezionato per giocare meglio a quei punti di forza).

In tutto, mentre il classico errore che muove un'applicazione web da REST è di abusare POST a fare assolutamente tutto quando GET, PUT e DELETE (e forse i metodi WebDAV) sarebbe superiore, non abbiate paura di usa il suo potere quando quelli non rispettano il conto, e non pensare che il "nuovo subordinato della risorsa" debba significare una piena risorsa longeva.


* Si noti che una risorsa "singolo" qui potrebbe essere composta da diverse risorse che possono avere il proprio URI, in modo che possa essere facile avere un unico DELETE che cancella più oggetti, ma se l'eliminazione di X cancella A , B & C allora è meglio essere ovvi che non puoi avere A, B o C se non hai X o la tua API non sarà comprensibile. Generalmente questo si riduce a ciò che viene modellato e quanto è ovvio che una cosa dipende da un'altra.

† Strettamente parlando, dato che è possibile inviare intestazioni cache indicanti che l'invio di un'entità identica allo stesso URI avrà gli stessi risultati, ma non esiste un software Web generico che faccia questo e il proprio il cliente personalizzato può semplicemente "ricordare" comunque l'opinione su una determinata immagine.

1

È difficile. Come con molti altri scenari, non esiste un modo assolutamente corretto per farlo. Devi cercare di interpretare i principi RESTful in termini di limiti della semantica di HTTP. (Per inciso, non penso sia giusto pensare che REST abbia semantica, REST è uno stile architettonico che viene comunemente usato con i servizi HTTP, ma può essere usato per qualsiasi tipo di interfaccia.)

Ho affrontato un situazione simile nel mio attuale progetto. Abbiamo scelto di utilizzare un POST ma il codice di risposta è un 200 (OK) anziché lo 201 (Resource Created) in genere restituito dalle API Web RESTful.

Problemi correlati