Mi sento un po 'triste nel vedere che dopo più di 10 anni non ci sono risposte che affermino come una cosa come richiesta nell'OP potrebbe essere progettata in un'architettura REST, quindi sento il bisogno di farlo ora.
Per prima cosa, cos'è REST ?! L'acronimo REST o ReST sta per "Rappresentational State Transfer" e definisce lo scambio dello stato di una risorsa in un determinato formato di rappresentazione. Il formato di rappresentazione è adatto al tipo di supporto negoziato. Nel caso del application/html
formato di rappresentazione può esserci un flusso di contenuto di testo in formato HTML che viene reso nel browser, probabilmente dopo aver applicato una formattazione del foglio di stile per posizionare determinati elementi in determinate posizioni.
REST è in linea di principio una generalizzazione del Web navigabile che tutti conosciamo, sebbene si rivolga a tutti i tipi di applicazioni e non solo ai browser. Pertanto, in base alla progettazione, gli stessi concetti che si applicano al Web si applicano anche a un'architettura REST. Una domanda come come ottenere qualcosa in modo "RESTful" si risolve nel rispondere alla domanda su come ottenere qualcosa in una pagina Web e quindi applicare gli stessi concetti al livello dell'applicazione.
Un calcolatore basato sul Web può in genere iniziare con una "pagina" che consente di immettere alcuni valori da calcolare prima di inviare i dati immessi al server. In HTML questo di solito si ottiene tramite <form>
elementi HTML che insegnano a un cliente i parametri disponibili da impostare, la posizione di destinazione a cui inviare la richiesta e il formato di rappresentazione da applicare al momento dell'invio dei dati di input. Questo può cioè assomigliare a questo:
<html>
<head>
...
</head>
<body>
<form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
<label for="firstNumber">First number:</label>
<input type="number" id="firstNumber" name="firstNumber"/>
<label for="secondNumber">Second number:</label>
<input type="number" id="secondNumber" name="secondNumber"/>
<input type="submit" value="Add numbers"/>
</form>
</body>
</html>
L'esempio sopra, ad esempio, afferma che ci sono due campi di input che possono essere compilati dall'utente o da alcuni altri automi e che, invocando l'elemento di input di invio, il browser si occupa di formattare i dati di input in un application/x-www-form-urlencoded
formato di rappresentazione che viene inviato nella posizione di destinazione menzionata tramite il metodo di richiesta HTTP specificato, POST
in questo caso. Se entriamo 1
nel firstNumber
campo di input e 2
nel secondNumber
campo di input, il browser genererà una rappresentazione firstNumber=1&secondNumber=2
e la invierà come payload corporeo della richiesta effettiva alla risorsa di destinazione.
La richiesta HTTP non elaborata inviata al server può quindi apparire così:
POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html
firstNumber=1&secondNumber=2
Il server può eseguire il calcolo e rispondere con un'ulteriore pagina HTML che contiene il risultato del calcolo, poiché la richiesta indicava che il client comprende questo formato.
Come ha già sottolineato Breton, non esiste un URL o un URI "RESTful". Un URI / URL è il suo genere di cose e non dovrebbe trasmettere alcun significato a un cliente / utente. Nell'esempio della calcolatrice sopra un utente semplicemente non è interessato a dove inviare i dati ad esso è solo interessato al fatto che quando si innesca il campo di input di invio la richiesta viene inviata. Tutte le informazioni richieste necessarie per eseguire l'attività dovrebbero già essere fornite dal server.
Un browser potrebbe anche non essere consapevole del fatto che la richiesta sta effettivamente alimentando una calcolatrice con alcuni parametri di input, potrebbe anche essere una sorta di modulo d'ordine che restituisce solo la rappresentazione del modulo successivo per continuare il processo di ordinazione o un tipo completamente diverso di risorsa. Esegue semplicemente ciò che le specifiche HTML richiedono in tal caso e non potrebbe importare di meno di ciò che il server sta effettivamente facendo. Questo concetto consente a un browser di utilizzare lo stesso formato di rappresentazione per fare qualsiasi tipo di cose come ordinare alcune cose dal tuo negozio online preferito, chattare con i tuoi migliori amici, accedere a un account online e così via.
La convenienza di alcuni elementi, come nel caso del campo di input di invio che di solito è reso come pulsante, definisce cosa dovresti fare con esso. Nel caso di un pulsante o un collegamento, in pratica ti dice di fare clic su di esso. Altri elementi possono trasmettere diverse convenzioni. Tale convenienza può anche essere espressa tramite relazioni di collegamento come ad esempio conpreload
collegamenti annotati che sostanzialmente dicono a un cliente che può già caricare il contenuto della risorsa collegata in background poiché l'utente probabilmente afferrerà successivamente questo contenuto. Tali relazioni di collegamento dovrebbero ovviamente essere standardizzate o seguire il meccanismo di estensione per i tipi di relazione come definito dal collegamento Web .
Questi sono i concetti fondamentali che vengono utilizzati sul Web e che dovrebbero essere utilizzati anche in un'architettura REST. Secondo "Zio Bob" Robert C. Martin un'architettura riguarda le intenzioni e l'intenzione dietro l'architettura REST è il disaccoppiamento dei client dai server per consentire ai server di evolversi liberamente in futuro senza temere che rompano i client. Ciò purtroppo richiede molta disciplina in quanto è così facile introdurre l'accoppiamento o aggiungere soluzioni di correzione rapida per portare a termine il lavoro e andare avanti. Come ha sottolineato Jim Webber in un'architettura REST, tu, come fornitore di servizi, dovresti tentare di progettare un protocollo di applicazione di dominio simile a un gioco per computer basato su testo degli anni '70 che i client seguiranno fino a quando non raggiungeranno la fine di un processo.
Ciò che un sacco di cosiddette API "REST" fanno purtroppo nella realtà è tutt'altro che quello. Si vede lo scambio di dati per lo più basati su JSON che è specificato in una documentazione esterna specifica dell'API che di solito è difficile da integrare dinamicamente al volo. Il formato che assomiglia a una richiesta è anche codificato nella documentazione esterna che porta a un sacco di implementazione che interpreta gli URI restituire caratteri predefinitiinvece di utilizzare un formato di rappresentazione comune che viene negoziato in anticipo. Ciò impedisce ai server di cambiare poiché i client ora si aspettano di ricevere un determinato formato di dati (nota non formato di rappresentazione!) Per gli URI predefiniti. Questo scambio personalizzato di formati di dati impedisce inoltre ai client di interagire con altre API, in quanto il "formato di dati" è generalmente soggetto a un'API specifica. Conosciamo questo concetto del passato da tecnologie RPC come Corba, RMI o SOAP che condanniamo come in qualche modo malvagie, anche se Peppol è passato di nuovo ad esso sostituendo AS2 con AS4 come protocollo di trasferimento predefinito di recente.
Per quanto riguarda l'effettiva domanda posta, l'invio di dati come file CSV non è diverso dall'uso di application/x-www-form-urlencoded
rappresentazioni o cose simili. Jim Webber ha chiarito che, dopo tutto, HTTP è solo un protocollo di trasporto il cui dominio dell'applicazione è il trasferimento di documenti sul Web . Il client e il server dovrebbero almeno supportare entrambi text/csv
come definito in RFC 7111 . Questo file CSV potrebbe essere generato come conseguenza dell'elaborazione di un tipo di supporto che definisce gli elementi del modulo, un elemento di destinazione o un attributo a cui inviare la richiesta nonché il metodo HTTP per eseguire il caricamento della configurazione.
Esistono un paio di tipi di media che supportano moduli come HTML , HAL Form , halform , ion o Hydra . Al momento, tuttavia, non sono a conoscenza di un tipo di supporto che può codificare automaticamente i dati di input text/csv
direttamente, quindi potrebbe essere necessario definirli e registrarli con nel registro dei tipi di supporto di IANA .
Il caricamento e il download dell'intero set di parametri non dovrebbe essere un problema, suppongo. Come accennato in precedenza, l'URI di destinazione non è rilevante in quanto un client utilizzerà l'URI solo per recuperare nuovi contenuti da elaborare. Anche il filtro per data commerciale non dovrebbe essere difficile. Qui il server dovrebbe tuttavia il client con tutte le possibilità che il client può semplicemente scegliere. Negli ultimi anni GraphQL e RestQL si sono evoluti, introducendo un linguaggio simile a SQL che può essere indirizzato a un determinato endpoint per ottenere una risposta filtrata. Tuttavia, in un vero senso REST, ciò viola l'idea alla base di REST come a) GraphQL, ovvero utilizza solo un singolo endpoint che impedisce in qualche modo l'utilizzo ottimale della cache eb) richiede la conoscenza dei campi disponibili a monte, il che può portare all'introduzione di un accoppiamento di client al modello di dati di base della risorsa.
L'attivazione o la disattivazione di determinati parametri di configurazione è semplicemente una questione di innesco dei controlli hypermedia che forniscono questa convenienza. Nei moduli HTML questa potrebbe essere una semplice casella di controllo o una selezione su più righe in un elenco o quel tipo. A seconda del modulo e del metodo che definisce potrebbe potenzialmente inviare l'intera configurazione tramite PUT
o essere intelligente sulle modifiche apportate ed eseguire solo un aggiornamento parziale tramite PATCH
. Quest'ultimo richiede sostanzialmente un calcolo della rappresentazione di cambiamento a quella aggiornata e alimenta il server con i passaggi necessari per trasformare la rappresentazione corrente in quella desiderata. Secondo la specifica PATH, questo deve essere fatto all'interno di una transazione in modo da applicare tutti o nessuno dei passaggi.
HTTP consente e incoraggia un server a convalidare anticipatamente una richiesta ricevuta prima di applicare le modifiche. Per PUT le specifiche indicano:
Un server di origine DOVREBBE verificare che la rappresentazione PUT sia coerente con eventuali vincoli che il server ha per la risorsa di destinazione che non può o non sarà modificata dal PUT. Ciò è particolarmente importante quando il server di origine utilizza le informazioni di configurazione interne relative all'URI al fine di impostare i valori per i metadati di rappresentazione sulle risposte GET. Quando una rappresentazione PUT non è coerente con la risorsa di destinazione, il server di origine DOVREBBE renderle coerenti, trasformando la rappresentazione o modificando la configurazione della risorsa, oppure rispondendo con un messaggio di errore appropriato contenente informazioni sufficienti per spiegare perché la rappresentazione non è adatta. Sono suggeriti i codici di stato 409 (Conflitto) o 415 (Tipo di supporto non supportato),
Ad esempio, se la risorsa di destinazione è configurata per avere sempre un tipo di contenuto di "testo / html" e la rappresentazione in corso PUT ha un tipo di contenuto di "immagine / jpeg", il server di origine dovrebbe eseguire una delle seguenti operazioni:
un. riconfigurare la risorsa di destinazione per riflettere il nuovo tipo di supporto;
b. trasformare la rappresentazione PUT in un formato coerente con quello della risorsa prima di salvarla come nuovo stato della risorsa; o,
c. respingere la richiesta con una risposta 415 (tipo di supporto non supportato) che indica che la risorsa di destinazione è limitata a "text / html", forse includendo un collegamento a una risorsa diversa che sarebbe una destinazione adatta per la nuova rappresentazione.
HTTP non definisce esattamente in che modo un metodo PUT influisce sullo stato di un server di origine oltre a ciò che può essere espresso dall'intento della richiesta dell'agente utente e dalla semantica della risposta del server di origine. ...
Per riassumere questo post, è necessario utilizzare un tipo di supporto esistente che consenta di insegnare a un client i parametri di input richiesti o supportati, la posizione di destinazione a cui inviare la richiesta, l'operazione da utilizzare e il tipo di supporto la richiesta deve essere formattata o definita la propria che si registra con IANA. Quest'ultimo potrebbe essere necessario se si desidera convertire l'input intext/csv
e quindi caricare la rappresentazione CSV sul server. La convalida dovrebbe avvenire prima che le modifiche vengano applicate alla risorsa. L'URI effettivo non dovrebbe essere rilevante per i clienti se non quello di determinare dove inviare la richiesta e in quanto tale può essere liberamente scelto da te, il responsabile del servizio. Seguendo questi passaggi ottieni praticamente la libertà di cambiare il tuo server in qualsiasi momento e i client non si romperanno di conseguenza se supportano i tipi di media utilizzati.