Domanda

Faccio fatica a 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 riguarderebbero:

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

Ritengo che l'approccio riposante sarebbe 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

??

È stato utile?

Soluzione

Forse qualcosa del tipo:

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

{ "active": true }

Altri suggerimenti

Principi generali per una buona progettazione degli URI:

  • Non utilizzare i parametri di query per modificare lo stato
  • Non utilizzare percorsi in casi misti se puoi aiutarlo; le lettere minuscole sono le migliori
  • Non non utilizzare estensioni specifiche dell'implementazione nei tuoi URI (.php, .py, .pl, ecc.)
  • Non rientrare in RPC con i tuoi URI
  • Do limita il più possibile lo spazio URI
  • Do mantieni i segmenti di percorso brevi
  • Do preferisce / resource o / resource / ; crea 301 reindirizzamenti da quello che non usi
  • Do utilizza i parametri di query per la sub-selezione di una risorsa; ovvero impaginazione, query di ricerca
  • Do sposta cose fuori dall'URI che dovrebbero essere in un'intestazione HTTP o in un corpo

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

Principi generali per la scelta del metodo HTTP:

  • Non non usare mai GET per cambiare 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 utilizzare 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 potrebbe essere ragionevole memorizzare nella cache
  • Non eseguire un'operazione che non è idempotent con PUT
  • Do usa GET il più possibile
  • Do usa POST preferibilmente a PUT in caso di dubbi
  • Do usa POST ogni volta che devi fare qualcosa che sembra simile a RPC
  • Do usa PUT per classi di risorse più grandi o gerarchiche
  • Esegui utilizza ELIMINA preferibilmente POST per rimuovere risorse
  • Do usa GET per cose come i calcoli, a meno che l'input non sia grande, nel qual caso usa POST

Principi generali di progettazione di servizi Web con HTTP:

  • Non inserire metadati nel corpo di una risposta che dovrebbe essere in un'intestazione
  • Non mettere i metadati in una risorsa separata a meno che includerlo crei un notevole sovraccarico
  • Do utilizza il codice di stato appropriato
    • 201 Created dopo 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 Request quando qualcuno esegue un'operazione su dati chiaramente falsi; per la tua applicazione questo potrebbe essere un errore di convalida; in genere riserva 500 eccezioni non rilevate
    • 401 Non autorizzato quando qualcuno accede alla tua API senza fornire un'intestazione Autorizzazione necessaria o quando le credenziali all'interno di Autorizzazione non sono valide; non utilizzare questo codice di risposta se non ti aspetti le credenziali tramite un'intestazione Autorizzazione .
    • 403 Proibito quando qualcuno accede alla tua API in un modo che potrebbe essere dannoso o se non è autorizzato
    • 405 Metodo non consentito quando qualcuno utilizza POST quando avrebbe dovuto usare PUT, ecc.
    • 413 Entità richiesta troppo grande quando qualcuno tenta di inviarti un file inaccettabilmente grande
    • 418 Sono una teiera quando tento di preparare il caffè con una teiera
  • Esegui utilizza le intestazioni di memorizzazione nella cache ogni volta che puoi
      Le intestazioni
    • ETag sono utili quando puoi facilmente ridurre una risorsa a un valore hash
    • Last-Modified dovrebbe indicarti che mantenere una data e l'ora di quando le risorse vengono aggiornate è una buona idea
    • Cache-Control e Expires dovrebbero ricevere valori sensibili
  • Fai tutto il possibile per onorare le intestazioni della cache in una richiesta ( If-None-Modified , If-Modified-Since )
  • Do usa i reindirizzamenti quando hanno senso, ma questi dovrebbero essere rari per un servizio web

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

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 (coloro 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 finché non lo fai! Solo allora il tuo team avrà un'idea di ciò che deve essere costruito.

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

Ci sono molti buoni libri in questa parte del processo di progettazione del software. Due che posso raccomandare sono Domain Driven Design e Pattern di analisi .

Il design dei tuoi URL non ha nulla a che vedere con l'applicazione RESTful o no. la frase "RESTful URLS" è quindi una sciocchezza.

Penso che dovresti fare qualche altra lettura su cosa sia effettivamente 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 al modo in cui l'applicazione funziona da zero. O quello, o abbandonare REST e fare semplicemente la tua app come app RPC.

Hrmmm 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, devi solo aggiungere

get [parametriurl] / validationresults

post [paramatersurl]

body: {comando: " attiva "}

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

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 "presentata". 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.

es. Crea alcune risorse come,

/ActiveParameters
/ValidatedParameters

Se vuoi rendere attivo un set di parametri, allora aggiungi quel set alla collezione 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 può essere fatta con / ValidatedParameters. Se i parametri non sono validi, il server può restituire " Richiesta non valida " alla richiesta di aggiungere i parametri alla raccolta di parametri convalidati.

Suggerirei 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
<

Controlla 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': '...'}
< }
<

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 inizio_data, termine (in mesi o anni), periodo (quando l'interesse è composto), tasso di interesse e 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.

Modifica: in effetti l'URI avrebbe impedito alle richieste GET 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.

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

Questo 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top