Progettazione dell'API REST per pagine Web con procedure guidate

9

Ho una pagina web con il formato wizard. Il pulsante di invio all'API sarà nel 4 ° passaggio della procedura guidata. Tuttavia, desidero che i dati immessi vengano archiviati nel database prima di passare al passaggio successivo della procedura guidata. Voglio anche che l'API REST funzioni per le pagine con una singola scheda.

Quindi ho progettato l'API per prendere un parametro di query action = draft o submit. Se l'azione è bozza, solo alcuni campi sono obbligatori. Se l'azione è inviata, tutti i campi sono obbligatori. Le convalide nel livello di servizio dell'API REST verranno eseguite in base al parametro di query. Sembra che debba specificare esplicitamente le clausole if / else nella documentazione. Questa è una forma accettabile di design RESTful? Quale sarebbe il miglior design con questi requisiti?

    
posta TechCrunch 09.02.2016 - 16:07
fonte

3 risposte

6

Poiché si desidera mantenere le cose sul server tra una procedura e l'altra, sembra perfettamente accettabile considerare ogni passaggio come una risorsa separata. Qualcosa in questo senso:

POST /wizard/123/step1
POST /wizard/123/step2
POST /wizard/123/step3

Includendo i link ipermediali nella risposta, puoi informare il cliente su cosa può fare dopo questo passaggio: andare avanti o indietro per i passaggi intermedi e nulla per il passaggio finale. Puoi vedere un esempio in Figura 5 qui .

    
risposta data 10.02.2016 - 13:46
fonte
2

Ho avuto bisogno di fare qualcosa di simile qualche tempo fa, e quanto segue descrive quello che finiamo con.

Abbiamo due tabelle, Item e UnfinishedItem. Quando l'utente compila i dati con la procedura guidata, i dati vengono memorizzati nella tabella UnfinishedItem. Ad ogni passo della procedura guidata, il server convalida i dati immessi durante quel passaggio. Al termine della procedura guidata, la procedura guidata esegue il rendering di un modulo nascosto / di sola lettura in una pagina di conferma che mostra tutti i dati da inviare. L'utente può rivedere questa pagina e tornare alla fase pertinente per correggere gli errori. Una volta che l'utente è soddisfatto delle proprie immissioni, l'utente fa clic su Invia e la procedura guidata invia quindi tutti i dati nei campi modulo nascosto / di sola lettura al server API. Quando il server API elabora questa richiesta, esegue nuovamente tutte le convalide eseguite durante ogni fase della procedura guidata ed esegue ulteriori convalide che non rientrano nei singoli passaggi (ad esempio convalide globali, convalide costose). Al termine di tutte le convalide, il server API crea una voce nella tabella degli articoli.

I vantaggi dell'approccio a due tabelle:

  • nel database, puoi avere vincoli più stretti sulla tabella degli articoli rispetto alla tabella UnfinishedItem; non è necessario disporre di colonne facoltative che saranno effettivamente necessarie al termine della procedura guidata.

  • Le query aggregate sugli articoli finiti per la creazione di rapporti sono più facili in quanto non è necessario ricordare di escludere gli UnfinishedItems. Nel nostro caso, non abbiamo mai avuto bisogno di fare query aggregate tra Item e UnfinishedItems, quindi questo non è un problema.

Lo svantaggio:

  • È soggetto a duplicazione della logica di convalida. Il framework web che abbiamo usato, Django, rende questo un po 'più sopportabile, poiché abbiamo usato l'ereditarietà del modello con un po' di meta magia per modificare i vincoli che dobbiamo essere diversi in Item e UnfinishedItem. Django genera la maggior parte del database e la convalida del modulo dal modello, e abbiamo solo bisogno di hackerare alcune convalide aggiuntive su di esso.

Altre possibilità che ho considerato e perché non siamo andati con loro:

  • salvataggio dei dati nei cookie o nella memoria locale: l'utente non può continuare la propria trasmissione da un dispositivo diverso o se cancella la cronologia del browser
  • memorizza l'UnfinishedItem come dati non strutturati (ad es. JSON) sul database o sul datastore secondario: dovrò definire la logica di analisi e non posso utilizzare la validazione automatica del modello / modulo di Django.
  • fai la validazione per passo sul lato client: dovrò duplicare la logica di validazione tra Python / Django e JavaScript.
risposta data 10.02.2016 - 12:43
fonte
0

L'ho implementato in modo simile a un mix di soluzioni @ guillauma31 e @Lie Ryan.

Ecco i concetti chiave:

  1. C'è una procedura guidata in 3 fasi che può essere parzialmente mantenuta fino al completamento.
  2. Ogni fase ha la sua risorsa (es .: /users/:id_user/profile/step_1 , .../step_2 , ecc.)
  3. In ogni passaggio, lo stato di dati e di completamento può essere recuperato tramite richieste GET e persistere attraverso le richieste PATCH.
  4. Ogni risorsa ha le proprie regole di convalida sui dati inseriti.
  5. Ogni passo restituisce una chiave che deve essere utilizzata nell'input del passaggio successivo per garantire la sequenza. Una volta utilizzato o ne viene generato uno nuovo, questo token scade.
  6. Nel passaggio finale, abbiamo tutti i dati necessari sul database e viene visualizzata una schermata di conferma. Questa conferma chiama un'altra risorsa per contrassegnare i dati come completi (es .: .../profile/confirm ). Questa risorsa non ha bisogno di ricevere di nuovo tutti i dati. Segna solo i dati corretti e completi.
  7. Esiste una routine pianificata che cancella queste voci incomplete che hanno più di pochi giorni.

I giocatori di front-end devono occuparsi dei token per ottenere il flusso avanti e indietro della procedura guidata.

L'API è stateless e atomica.

Per far funzionare un "wizard in un passo" con questa configurazione, devi modificare alcune cose, come rimuovere il flusso di token o creare una risorsa per restituire token in base al tipo di procedura guidata o anche creare una nuova risorsa solo per riempire questa procedura guidata a passo singolo specifica (come PUT /users/:id_user/profile/ ).

    
risposta data 26.02.2016 - 01:13
fonte

Leggi altre domande sui tag