Come creare URL REST senza verbi?


283

Sto lottando per determinare come progettare URL riposanti. Sono tutto per l'approccio riposante di usare URL con nomi e non i verbi non capiscono come farlo.

Stiamo creando un servizio per implementare un calcolatore finanziario. Il calcolatore prende un sacco di parametri che cariceremo tramite un file CSV. I casi d'uso implicherebbero:

  1. Carica nuovi parametri
  2. Ottieni gli ultimi parametri
  3. Ottieni parametri per una determinata data lavorativa
  4. Rende attivo un set di parametri
  5. Convalida una serie di parametri

Raccolgo che l'approccio riposante sarebbe quello di avere i seguenti URL di tipo:

/parameters
/parameters/12-23-2009

È possibile ottenere i primi tre casi d'uso con:

  1. POST in cui si include il file dei parametri nella richiesta di post
  2. OTTIENI il primo URL
  3. OTTIENI il secondo URL

Ma come si fa il 4o e il 5o caso d'uso senza verbo? Non avresti bisogno di URL come:

/parameters/ID/activate
/parameters/ID/validate

??


3
Preferisco PATCH piuttosto che POST per l'aggiornamento parziale.
user2016971

Risposte:


71

Forse qualcosa del tipo:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }

1
POSTva bene se è necessario eseguire una "procedura" come verificare i parametri ogni volta che si invia una richiesta. Ma quando si modifica lo stato (dell'applicazione) della risorsa, si aggiorna effettivamente la risorsa esistente, non si crea una nuova risorsa o si invia una richiesta di elaborazione.
Andrey Vlasovskikh,

19
PUT serve a creare una nuova risorsa o a posizionare (in tutto, non in parte) una nuova risorsa in un determinato URL. Non vedo come PUT si adatta a questo caso.
Bretone,

30
In realtà, POSTvs PUTnon è esattamente come insertvs update. PUTaggiorna la risorsa corrispondente al percorso specificato o crea una nuova risorsa corrispondente al percorso indicato. POSTcrea una nuova risorsa da qualche parte. Ad esempio, PUT /blog/posts/3/comments/5aggiornerà il commento appropriato, mentre POST /blog/posts/3/commentscreerà una nuova commentrisorsa (e dovrebbe restituire il percorso alla nuova risorsa nella risposta).
yfeldblum,

23
@Justice @Breton La differenza più importante è che PUTè idempotente mentre POSTnon lo è. Di solito dovresti porre quanti più vincoli su ciò che fornisci come risultato possibile. Rimanere con PUTfornisce maggiori informazioni al cliente del servizio.
Andrey Vlasovskikh,

3
La risorsa potrebbe anche essere stata / parametri / stato e il corpo della richiesta avrebbe potuto essere solo "attivo". In questo modo stai in qualche modo posizionando una risorsa completamente nuova in un particolare URL.
Carlos Aguayo,

991

Principi generali per una buona progettazione degli URI:

  • Non utilizzare i parametri di query per modificare lo stato
  • Non usare percorsi a caso misto se puoi aiutarlo; il minuscolo è il migliore
  • Non utilizzare estensioni specifiche dell'implementazione nei tuoi URI (.php, .py, .pl, ecc.)
  • Non cadere in RPC con i tuoi URI
  • Non limitare lo spazio URI, per quanto possibile
  • Tieni i segmenti del percorso brevi
  • Do preferiscono sia /resourceo /resource/; crea 301 reindirizzamenti da quello che non usi
  • Fare i parametri di utilizzo di query per sub-selezione di una risorsa; cioè impaginazione, query di ricerca
  • Do mossa roba fuori l'URI che dovrebbe essere in un corpo header HTTP o un

(Nota: non ho detto "RESTful URI design"; gli URI sono essenzialmente opachi in REST.)

Principi generali per la scelta del metodo HTTP:

  • Non usare mai GET per modificare lo stato; questo è un ottimo modo per far rovinare la giornata a Googlebot
  • Non utilizzare PUT a meno che non si stia aggiornando un'intera risorsa
  • Non usare PUT a meno che tu non possa anche legittimamente fare un GET sullo stesso URI
  • Non utilizzare POST per recuperare informazioni di lunga durata o che potrebbero essere ragionevoli da memorizzare nella cache
  • Non eseguire un'operazione non idempotente con PUT
  • Fare uso GET per quanto possibile,
  • Fare uso POST a preferenza di PUT in caso di dubbio
  • Fare uso POST ogni volta che si deve fare qualcosa che si sente RPC-like
  • Fare uso PUT per le classi di risorse che sono più grandi o gerarchico
  • Evitare l'uso DELETE a preferenza di POST alle risorse rimuovere
  • Do uso GET per cose come i calcoli, a meno che l'input è di grandi dimensioni, in cui POST caso d'uso

Principi generali di progettazione di servizi Web con HTTP:

  • Non inserire metadati nel corpo di una risposta che dovrebbe trovarsi in un'intestazione
  • Non mettere i metadati in una risorsa separata a meno che includerlo crei un notevole sovraccarico
  • Non utilizzare il codice di stato appropriata
    • 201 Createddopo aver creato una risorsa; la risorsa deve esistere al momento dell'invio della risposta
    • 202 Accepted dopo aver eseguito un'operazione correttamente o aver creato una risorsa in modo asincrono
    • 400 Bad Requestquando qualcuno esegue un'operazione su dati chiaramente falsi; per la tua applicazione questo potrebbe essere un errore di convalida; in genere riserva 500 per eccezioni non rilevate
    • 401 Unauthorizedquando qualcuno accede alla tua API o senza fornire Authorizationun'intestazione necessaria o quando le credenziali all'interno di Authorizationnon sono valide; non utilizzare questo codice di risposta se non ti aspetti le credenziali tramite Authorizationun'intestazione.
    • 403 Forbidden quando qualcuno accede alla tua API in un modo che potrebbe essere dannoso o se non è autorizzato
    • 405 Method Not Allowed quando qualcuno usa POST quando avrebbe dovuto usare PUT, ecc
    • 413 Request Entity Too Large quando qualcuno tenta di inviarti un file inaccettabilmente grande
    • 418 I'm a teapot quando si tenta di preparare il caffè con una teiera
  • Fare uso intestazioni di cache ogni volta che potete
    • ETag le intestazioni sono utili quando puoi facilmente ridurre una risorsa a un valore hash
    • Last-Modified dovrebbe indicarti che mantenere una data e l'ora di aggiornamento delle risorse è una buona idea
    • Cache-Controle Expiresdovrebbero ricevere valori sensibili
  • Fai tutto il possibile per onorare le intestazioni della cache in una richiesta ( If-None-Modified, If-Modified-Since)
  • Do uso redirect quando hanno un senso, ma questi dovrebbero essere raro per un servizio web

Per quanto riguarda la tua domanda specifica, POST dovrebbe essere usato per # 4 e # 5. Queste operazioni rientrano nella linea guida "RPC-like" sopra. Per # 5, ricorda che il POST non deve necessariamente essere utilizzato Content-Type: application/x-www-form-urlencoded. Questo potrebbe essere altrettanto facilmente un payload JSON o CSV.


11
413 è inteso per la dimensione della richiesta che ti viene inviata in modo da poter rifiutare educatamente qualcuno che ti invia concerti di dati, spesso in combinazione con 411 in modo da costringere le persone a dirti quanto viene inviato. Per l'esempio dato contro 413, penso che 400 sarebbe una risposta più appropriata.
Garry Shutler,

5
+1 poiché questa è una grande risorsa. Tuttavia, è una risorsa generale e non risponde direttamente alla domanda. Ciò dovrebbe idealmente includere un paragrafo aggiuntivo con una risposta specifica.
Samuel Neff,

@GarryShutler Buona cattura, hai perfettamente ragione. Grazie per la modifica.
Bob Aman,

1
Sì, useresti PUT solo nei casi in cui stai sovrascrivendo l'intero oggetto. Tuttavia, direi che PATCH o POST sono ragionevoli nel caso di un aggiornamento parziale di una risorsa. PATCH è più chiaro in termini di operazione che verrà eseguita, ma poiché non tutti i client sono nemmeno in grado di emettere una richiesta PATCH , è del tutto appropriato consentire invece un POST , e potrei persino spingermi fino a sostenere che un Il POST deve essere sempre consentito come fallback se si utilizza PATCH .
Bob Aman,

1
+1 per 409 errori. Un errore 400 è qualcosa che potrebbe essere risolto con una sufficiente convalida sul lato client. Un 409 chiarisce che la richiesta stessa era accettabile e coerente, ma è in conflitto con alcuni aspetti dello stato del server (di solito controlli di concorrenza, ma teoricamente qualsiasi vincolo di non input).
Claytond

18

Ogni volta che sembra che tu abbia bisogno di un nuovo verbo, pensa invece a trasformarlo in un sostantivo. Ad esempio, trasforma "attiva" in "attivazione" e "convalida" in "convalida".

Ma proprio da quello che hai scritto direi che la tua applicazione ha problemi molto più grandi.

Ogni volta che viene proposta una risorsa chiamata 'parametro', dovrebbe inviare bandiere rosse nella mente di ogni membro del team di progetto. 'parametro' può letteralmente applicarsi a qualsiasi risorsa; non è abbastanza specifico.

Cosa rappresenta esattamente un 'parametro'? Probabilmente un numero di cose diverse, ognuna delle quali dovrebbe avere una risorsa separata dedicata ad essa.

Un altro modo per arrivare a questo - quando discutete la vostra applicazione con gli utenti finali (quelli che presumibilmente sanno poco della programmazione) quali sono le parole che usano loro stessi ripetutamente?

Queste sono le parole su cui dovresti progettare la tua applicazione.

Se non hai ancora avuto questa conversione con potenziali utenti, ferma subito tutto e non scrivere un'altra riga di codice fino a quando non lo fai! Solo allora il tuo team avrà un'idea di ciò che deve essere costruito.

Non so nulla di software finanziario, ma se dovessi indovinare, direi che alcune delle risorse potrebbero andare con nomi come "Rapporto", "Pagamento", "Trasferimento" e "Valuta".

Ci sono una serie di buoni libri su questa parte del processo di progettazione del software. Due che posso consigliare sono i modelli di analisi e progettazione basati su dominio .


1
Questo è davvero un buon punto. È facile perdere se sei nello stato d'animo per l'elaborazione della logica formale e del ragionamento. Non importa quale sia X, purché si adatti in modo valido alle altre parti. I fattori umani scivolano via.
Bretone,

1
A volte trovo utile convertire le parole in una "risorsa di elaborazione" come "attivatore" o "validatore". Secondo RFC 2616 POST può essere utilizzato per "Fornire un blocco di dati ... a un processo di gestione dei dati"
Darrel Miller,

Inteso. In questo caso gli utenti fanno riferimento ai dati come "parametri" (o "parametri di rischio" o qualcosa di simile). L'elenco dei parametri contiene molti tipi diversi di impostazioni, ma i parametri vengono sempre caricati come un intero set (in un file CSV).
Marcus Leon,

@Marcus - sembra un caso davvero insolito. Forse se spiegassi in dettaglio cosa fa la tua app, saremmo in grado di offrire suggerimenti migliori per identificare le risorse.
Rich Apodaca,

1
"quando si discute della propria domanda con gli utenti finali quali sono le parole che essi stessi usano ripetutamente?" ... e se fossero tutti verbi? XD
Amalgovinus

11

Il design dei tuoi URL non ha nulla a che fare con il fatto che l'applicazione sia RESTful o meno. La frase "URL RESTful" non ha quindi senso.

Penso che dovresti leggere ancora su cosa sia in realtà REST. REST tratta gli URL come opachi e come tali non sa cosa ci sia, se ci sono verbi o nomi o altro. Potresti comunque voler progettare i tuoi URL, ma si tratta dell'interfaccia utente, non di REST.

Detto questo, arriviamo alla tua domanda: gli ultimi due casi non sono RESTful e non rientrano in alcun tipo di schema riposante. Questi sono quelli che potresti chiamare RPC. Se prendi sul serio REST, dovrai ripensare il modo in cui l'applicazione funziona da zero. O abbandonare REST e fare semplicemente la tua app come app RPC.

Forse no.

L'idea qui è che devi trattare tutto come una risorsa, quindi una volta che un set di parametri ha un URL da cui puoi fare riferimento, aggiungi semplicemente:

GET [parametersurl]/validationresults

POST [paramatersurl]
body: {command:"activate"}

Ma ancora una volta, quella cosa attiva è RPC, non REST.


Indichi un punto interessante qui. Puoi approfondire ulteriormente come sarebbe l'approccio RESTful per qualcosa del genere?
Poezn,

Ho trascorso un po 'di tempo a leggere le risposte qui, e penso che la giustizia potrebbe essere su qualcosa. modella le singole proprietà dell'oggetto parametri come risorse individuali e utilizza il verbo PUT per sostituire il contenuto di quella proprietà in quella risorsa. Questo sta modellando lo stato di ogni oggetto come una raccolta di risorse e modificando lo stato come posizionando o rimuovendo o modificando la risorsa. Per quanto riguarda la validazione, hai solo bisogno di una risorsa che indichi magicamente se i parametri sono validi o meno, come sopra nella mia risposta. Andrebbe bene, purché non abbia effetti collaterali.
Bretone,

Naturalmente, ciò che fa "Activate" è semplicemente impostare una singola proprietà su true. Se deve fare qualcos'altro, allora non è ancora RESTful, e non sono sicuro di come lo modesteresti RESTfully.
Bretone,

Non credo che si possa dire che gli ultimi due casi non siano RESTful. In effetti Activate e Convalida sono solo modi indiretti per dire che la risorsa sta cambiando in un nuovo stato in una macchina a stati. REST è abbastanza in grado di modellarlo.
Darrel Miller,

@Darrel, penso che tu indichi una parte di REST che potrebbe essere una sfida per molte persone che non conoscono REST. Come è possibile implementare un'operazione "Convalida risorsa x"? Penso che la sfida sia che si tratti di un'operazione che potrebbe comportare un cambio di stato, ma il nuovo stato è il risultato della richiesta.
Sean,

6

I requisiti di attivazione e convalida sono situazioni in cui si sta tentando di modificare lo stato di una risorsa. Non è diverso che fare un ordine "completato", o qualche altra richiesta "inviata". Esistono numerosi modi per modellare questo tipo di cambiamento di stato ma uno che trovo che spesso funziona è creare risorse di raccolta per risorse dello stesso stato e quindi spostare la risorsa tra le raccolte per influenzare lo stato.

ad es. creare alcune risorse come

/ActiveParameters
/ValidatedParameters

Se si desidera rendere attivo un set di parametri, quindi aggiungere tale set alla raccolta ActiveParameters. È possibile passare l'insieme di parametri come corpo di entità oppure è possibile passare un URL come parametro di query, come indicato di seguito:

POST /ActiveParameters?parameter=/Parameters/{Id}

La stessa cosa si può fare con / ValidatedParameters. Se i parametri non sono validi, il server può restituire "Richiesta non valida" alla richiesta per aggiungere i parametri alla raccolta di parametri convalidati.


1

Vorrei suggerire le seguenti risorse e metodi Meta.

Rendi i parametri attivi e / o validali:

> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<

Verifica se i parametri sono attivi e validi:

> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
<     'active': true,
<     'require-valid': true,
<     'valid': {'status': false, 'reason': '...'}
< }
<

Per quanto ho capito, la domanda riguarda la denominazione degli URL riposanti, non la funzionalità, non è vero?
Poezn,

2
Una domanda limitata a "URL RESTful" è una domanda sbagliata e alla quale non si deve rispondere. La domanda dovrebbe invece essere ampliata per considerare "Risorse RESTful, con metodi e URL associati" e rispondere come tale.
yfeldblum,

A quanto ho capito, la domanda riguardava le convenzioni di denominazione degli URL e i metodi HTTP a cui la risorsa nominata avrebbe dovuto rispondere.
Andrey Vlasovskikh,

1

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/htmlformato 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-urlencodedformato di rappresentazione che viene inviato nella posizione di destinazione menzionata tramite il metodo di richiesta HTTP specificato, POSTin questo caso. Se entriamo 1nel firstNumbercampo di input e 2nel secondNumbercampo di input, il browser genererà una rappresentazione firstNumber=1&secondNumber=2e 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-urlencodedrappresentazioni 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/csvcome 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/csvdirettamente, 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 PUTo 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/csve 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.


0

Modifica: in effetti l'URI avrebbe impedito alle GETrichieste di rimanere idempotenti.


Per la convalida, tuttavia, l'uso di codici di stato HTTP per notificare la validità di una richiesta (per creare un nuovo o modificare un "parametro" esistente) si adatterebbe a un modello Restful.

Segnala con un 400 Bad Requestcodice di stato se i dati inviati sono / non sono validi e la richiesta deve essere modificata prima di essere reinviata ( Codici di stato HTTP / 1.1 ).

Ciò si basa sulla convalida al momento dell'invio, invece di differirlo come nel tuo caso d'uso. Le altre risposte hanno soluzioni adatte a quello scenario.


L'URI è pensato per essere un identificatore. L'uso di un determinato URL non dovrebbe avere effetti collaterali. Immagina cosa farebbe un proxy.
Bretone,

2
o google, del resto. Una volta ho letto una storia su un webstore che ha cancellato tutti i suoi prodotti da Google a causa di questo tipo di idiozia.
Bretone,

0

In un ambiente REST, ogni URL è una risorsa unica. Quali sono le tue risorse? Un calcolatore finanziario in realtà non ha risorse ovvie. Devi scavare in quelli che stai chiamando parametri ed estrarre le risorse. Ad esempio, un calendario di ammortamento per un prestito potrebbe essere una risorsa. L'URL del calendario potrebbe includere la data di inizio, il termine (in mesi o anni), il periodo (quando l'interesse è composto), il tasso di interesse e il principio iniziale. Con tutti questi valori, hai un calendario specifico di pagamenti:

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

Ora, non so cosa stai calcolando, ma il tuo concetto di un elenco di parametri non suona RESTful. Come ha detto qualcun altro, i tuoi requisiti sopra sembrano più XMLRPC. Se stai cercando REST, hai bisogno di nomi. I calcoli non sono sostantivi, sono verbi che agiscono sui sostantivi. Devi girarlo per estrarre i nomi dai tuoi calc.


5
Penso che sia un po 'sciocco usare le barre in avanti qui, cosa ci sarebbe di sbagliato in amort_cal? Data = 20-10-2009 e tipo = 30yrsfixed & period = mensile & rate = 5.0 & initialamount = 200000? A REST non importa se è una risorsa. Tuttavia, le specifiche URI si preoccupano. Come immagini i collegamenti relativi a lavorare con uno schema come questo?
Breton,

Sollevi comunque un buon punto. Questi "parametri" devono anche essere archiviati sul lato server? Se è solo un calcolo una tantum, perché non creare semplicemente uno spazio virtuale, in cui i parametri si trovano nell'URL. Finché non stai cambiando lo stato interno, dovrebbe andare bene.
Bretone

1
E i "parametri" non si applicano a una "risorsa". Una risorsa è una singola entità con un identificatore univoco. Il mio URL identifica una singola risorsa. Un URL con parametri indica una raccolta di risorse tra cui selezionare utilizzando i parametri.
jmucchiello,

2
REST non si basa su "Risorse CRUDing". Incollare tutti i parametri della query in segmenti di percorso non crea automaticamente un'interfaccia RESTful perché ora pensi di poter chiamare ogni permutazione una risorsa. Sfortunatamente non esiste un processo magico che puoi applicare per identificare quali risorse dovrebbero essere nel tuo sistema. Richiede un design accurato, non una formula meccanica.
Darrel Miller,

2
Ancora una volta, l'architettura REST non CURA ciò che è nell'URL. l'URL è pensato per essere opaco . Non importa riposare se si usano barre, punti e virgola o cuori unicode come seperatori. Leggi questo e rispondi a questo, non a quello che immagini che io stia dicendo.
Bretone,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.