Evitare il doppio POST

4

Stiamo implementando un webservice RESTful che consentirà alle applicazioni client di inviare documenti POST e memorizzerà il documento restituendo un identificatore univoco nella risposta. I client saranno per lo più applicazioni Spring MVC, ma non è necessario.

Le due applicazioni client su cui stiamo lavorando hanno vari JSP che contengono moduli HTML che conterranno elementi di file e altri attributi. Quindi un utente invierà un modulo tramite POST a un controller Spring nell'applicazione client. Il controllore leggerà i byte dal file e poi li POST al servizio RESTful, riceverà l'identificativo univoco indietro e memorizzerà l'identificatore univoco insieme alle altre informazioni dal modulo nel database.

Dato che ogni client può avere più JSP con attributi ampiamente variabili nei moduli, non vediamo un modo per inviare solo POST direttamente al servizio web RESTful.

Esiste un modo pulito per evitare il doppio POST?

Ho potuto vedere la possibilità di avere una finestra pop-up riutilizzabile che si occupa di inviare il documento al servizio web RESTful e quindi di mantenere l'ID del documento univoco nella sessione o in un campo nascosto nel modulo padre. Posso vedere due aspetti negativi: 1) l'utente potrebbe non gradire il passaggio in più al pop-up e 2) il documento potrebbe essere orfano se l'utente non invia la pagina padre.

MODIFICA / CHIARIMENTO: il problema non è che un POST venga inviato due volte alla stessa risorsa, ma piuttosto che sia necessario avere un POST da JSP a Controller all'interno dell'applicazione client e quindi un secondo POST degli stessi dati dal client applicazione alla risorsa REST.

    
posta Paul Croarkin 29.07.2014 - 15:49
fonte

1 risposta

2

Abbiamo affrontato lo stesso problema e, come altri hanno suggerito nei commenti, abbiamo reso i nostri POST idempotenti. Puoi restituire un codice diverso (nella famiglia 200) se il file era già lì, solo per informare il cliente (oppure puoi solo rispondere "200"). Nella nostra esperienza, questo funziona egregiamente con i dispositivi "non collegati" (smartphone); se hai bisogno di riprovare, ti basta riprovare, senza preoccuparti di duplicati. Puoi creare (e memorizzare) un UID basato sul contenuto del documento (un hash MD5 o SHA) e magari usarlo anche come ID del documento principale.

Abbiamo anche considerato che rendere il codice client più complicato, aggiungendo un GET per verificare se un particolare documento era già inserito:

  • OTTIENI (questo documento è presente?)
  • POST (inserisci documento)
  • ...

ma questo rende il client più pesante (specialmente se si calcola l'hash due volte). Non spreca molto la larghezza di banda (nel nostro caso, essendo su una rete cellulare, era un problema importante); il più delle volte, basta POST una volta e ricevi una risposta OK (il documento non era presente).

E comunque non risolverà il problema; se POST il documento da un'altra pagina subito dopo il GET? Tuttavia, puoi combinare i due approcci, se vedi che il doppio POST si verifica più volte nella tua applicazione web.

    
risposta data 01.08.2014 - 08:52
fonte

Leggi altre domande sui tag