In REST, è compreso discriminatore all'interno del payload JSON preferito per avere endpoint separati

1

Quindi immagina, ho un endpoint in cui è possibile effettuare il pagamento dell'abbonamento a una rivista.

Potrebbero esserci diversi tipi di abbonamento. ad es. settimanale, quindicinale, annuale, 5 anni ecc.

Per ciascuna sottoscrizione, la richiesta JSON per l'endpoint della sottoscrizione varia in modi leggermente diversi. Ad esempio, forse con l'abbonamento di 5 anni, potresti voler chiedere l'indirizzo di residenza, ma per l'abbonamento settimanale, forse non ti interessa. Pertanto, la convalida (e anche la logica aziendale) differisce leggermente in base al tipo di abbonamento.

La domanda è, che è il modo preferito per modellare gli endpoint:

  1. Hai un unico endpoint: /subscription nel JSON che viene inviato, hai una proprietà discriminante. Questo è: %codice% In modo che nell'implementazione di { name: "Joe", Age: 66, subscription_type: "weekly | monthly | fortnight | yearly | etc" } sia presente un codice che esegue una convalida diversa alla richiesta JSON ed esegue una logica di business diversa in base al valore di /subscription
  2. Avere endpoint separati per i diversi tipi di abbonamento. Ad esempio: subscription_type , /subscription/weekly ecc. E l'implementazione di ciascuno di questi endpoint riguarda solo la convalida e la logica di business specifiche per il loro tipo di abbonamento.

Qualche altra opzione possibile oltre a questi due che ho menzionato? C'è qualche buona pratica per trattare questo tipo di scenario?

    
posta dade 26.01.2018 - 17:41
fonte

4 risposte

3

La risorsa è un abbonamento per alcuni clienti. La durata, la data di inizio, ecc. Sono informazioni sull'abbonamento.

Se l'indirizzo della risorsa è, ad es. %codice%. In che modo customer/{id}/subscription/monthly il tipo di abbonamento dato l'ID cliente?

Sembra più pulito poter GET per ottenere informazioni sulla sottoscrizione di un cliente, GET {id}/subscription per creare una nuova sottoscrizione e PUT {id}/subscription per modificare una sottoscrizione esistente.

    
risposta data 26.01.2018 - 18:42
fonte
2

La tua richiesta è ortogonale allo stile architettonico RESTful.

REST è solo uno stile architettonico. Uno dei suoi presupposti è che non è necessario definire la propria semantica del protocollo all'interno di un altro protocollo e nascondere i dettagli delle convenzioni personalizzate facendo riferimento allo schema principale.

Ad esempio, non è possibile utilizzare gli "URI" per identificare le risorse e violare i requisiti di RFC 3986, che è la fonte autorevole per ciò che costituisce un URI ben formato. Non è possibile affermare che si sta utilizzando "HTTP" come protocollo e inviare richieste non identi che con una richiesta "GET"; una cosa del genere non ha senso all'interno dei requisiti di HTTP.

All'interno di questo quadro, il contributo principale che lo stile architettonico RESTful dà è la nozione secondo cui le transizioni di stato dell'applicazione richieste devono essere comunicate dal server al client.

Sembra che tu stia cercando di forzare una distinzione senza una differenza tra le tue iscrizioni e propagare questa distinzione attraverso la tua interfaccia.

Se l'interfaccia delle risorse è la stessa per tutte le "Iscrizioni", non produci nulla di valore per l'espressività di tale risorsa dividendola formalmente per uno dei suoi attributi. L'unica cosa che si ottiene facendo questo all'interno degli identificatori delle risorse è la perdita dell'implementazione del server interno attraverso l'astrazione del servizio.

Dalle informazioni che hai fornito, ti sembra di avere una singola entità: "Abbonamento"; pertanto, dovresti sforzarti di progettare una singola interfaccia tra i diversi tipi di "Abbonamento".

    
risposta data 26.01.2018 - 19:34
fonte
1

Is there any best case practice for dealing with this kind of scenario?

Ho scoperto che chiedevo "come faresti su un sito web?" è uno strumento molto potente per valutare i tuoi progetti.

For each subscription, the JSON request to the subscription endpoint varies in slightly different ways. For example, perhaps with the 5 years subscription, you might want to ask for the residential address, but for the weekly subscription, perhaps you do not care.

Quindi sembra avere più moduli per raccogliere dati dal cliente. Potrebbe esserci un modulo settimanale che raccoglie le informazioni necessarie in quel caso d'uso e un modulo di cinque anni che raccoglie un set di dati diverso. Ciascuna di queste forme avrebbe un attributo di azione; quando viene inviato un modulo, il client crea il payload appropriato e invia la richiesta all'endpoint descritto dal modulo.

Il nucleo della tua domanda, quindi, è; queste diverse forme dovrebbero avere un unico endpoint? o dovrebbero condividere un endpoint?

Metti in modo leggermente diverso: quali sono le implicazioni di questa scelta?

L'RFC 7234 descrive invalidazione della cache :

A cache MUST invalidate the effective Request URI (Section 5.5 of RFC7230) as well as the URI(s) in the Location and Content-Location response header fields (if present) when a non-error status code is received in response to an unsafe request method.

In altre parole, se POST alla stessa risorsa che OTTIENE la rappresentazione, allora gli intermediari possono sapere che una rappresentazione precedentemente archiviata della risorsa deve essere sfrattata .

Ciò significa, ad esempio, che puoi mettere i proxy di cache di fronte ai tuoi endpoint API e ottenere il comportamento corretto "gratuitamente". Allo stesso modo, i client che hanno una cache associata possono utilizzare gratuitamente la cache locale.

Naturalmente, se avessi intenzione di modificare la tua risorsa di iscrizione utilizzando PUT o < a href="https://tools.ietf.org/html/rfc5789"> PATCH , si otterrebbe la stessa risposta: inviare la richiesta non sicura alla risorsa stessa, in modo che l'invalidazione della cache funzioni come se fosse supposto.

È un commercio; accettiamo il vincolo sulla nostra scelta di endpoint, in cambio otteniamo il caching gratuito. Nel 2008, Fielding ha scritto

REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them.

Il caching non è un argomento potente per tutte le API . Se nel tuo caso non ha senso, non dovresti considerare questo argomento particolarmente convincente. Document la tua comprensione dei vincoli e vai avanti.

    
risposta data 27.01.2018 - 14:33
fonte
0

Il secondo modello, senza dubbio.

È quasi sempre una buona idea separare gli endpoint coerenti sui valori delle voci.

Avere un endpoint che può accettare attributi diversi se qualche altro attributo è stato inviato insieme è una cattiva idea, perché è:

  • Più difficile da capire
  • Più difficile da creare una buona documentazione
  • Più difficile da mantenere
  • Più difficile per creare versioni diverse della risorsa (se è il tuo caso).

Bonus

Se puoi salvare un abbonamento senza le informazioni sul tipo, ho un suggerimento: pensa a inviare le informazioni comuni in un POST separato a /subscription/ e invia le informazioni specifiche per ogni tipo in POST a ogni tipo, come: /subscription/{id}/type/weekly/ , /subscription/{id}/type/monthly/ , ecc.

    
risposta data 26.01.2018 - 17:52
fonte

Leggi altre domande sui tag