REST Webservices (post / put): quale tipo di parametro dovrei scegliere, e quando?

4

Su un webservice POST (o PUT), so che posso usare tre diversi tipi di parametri, posso inviare i miei parametri nel percorso dell'URL / objects / {path_param}, dopo un punto interrogativo nell'URL / oggetti? {param_name} = {Param_value} o nel corpo della richiesta.

Per i servizi web GET, utilizzo il percorso per identificare una risorsa e la query per aggiungere alcuni filtri quando la risorsa è una lista.

La mia domanda principale è "Quando dovrei scegliere di usare un percorso / query / corpo su un webservice POST / PUT?". Sulla base di ciò, è accettabile avere sia parametri di query che parametri di body sullo stesso webservice?

Per ora, l'unica differenza tra i parametri di query e del corpo che conosco è che i parametri di query possono essere inviati come parte dell'URL e possono quindi essere memorizzati nella cache o conservati nella cronologia del browser, quindi mi piacerebbe sapere l'altro differenze che dovrebbero essere prese in considerazione.

    
posta gvo 03.10.2016 - 12:05
fonte

2 risposte

2

Con il design di HTTP (RFC 7230-7235), ciascun endpoint rappresenta una cosa di cui il server tiene traccia, solitamente chiamata Resource . A volte quella risorsa è solo una cosa (come un singolo widget), ea volte è un gruppo di cose (o widget). L'URI è destinato a essere un identificatore univoco per un widget o un gruppo di widget.

La maggior parte delle API utilizza nomi e ID leggibili dall'uomo per identificare queste cose negli URI. Alcuni servizi orientati alla sicurezza non fanno questo, perché espongono le informazioni agli utenti finali che il servizio non vuole che abbiano. Tra le API leggibili dall'uomo, la convenzione è diventata usare nomi plurali per indicare collezioni, un nome plurale seguito da un identificatore univoco per indicare un singolo elemento in una raccolta. Questi possono nidificare: un singolo oggetto può avere una raccolta o un singolo oggetto che si desidera esporre direttamente. Quindi:

/widgets               > all the widgets the user can see
/widgets/12            > a specific widget
/widgets/12/texture    > a widget has zero or one textures
/widgets/12/colors     > a widget has zero or more colors
/widgets/12/colors/5   > color #5 of widget #12

L'approccio sopra indicato è in genere chiamato RESTful , anche se REST è in realtà molto più di questo. L'altro approccio comune è chiamato Remote Procedure Calls o RPC in breve. In RPC, gli endpoint rappresentano istruzioni per il server, ad esempio /writeEndOfYearCsv . Se un cliente dovesse chiamare quell'URL con un POST, la risposta potrebbe eseguire lo streaming di un file CSV con il rapporto di fine anno. RPC sta calando in popolarità perché si crede che sia più difficile da mantenere nel tempo. RPC correttamente scritto utilizzerà solo le chiamate POST e GET.

I parametri di query, definiti in RFC 3986 , vengono utilizzati per restringere i dettagli di una risposta a un URI. Vengono utilizzati più spesso con "risorse di raccolta", ad esempio /widgets?shape=round , per limitare il contenuto della raccolta. In generale, vengono utilizzati per fornire informazioni al server su come costruire la risposta.

Ad esempio, /widgets/12?expand=texture potrebbe restituire una risorsa widget con le informazioni sulla trama incorporate in essa, mentre /widgets/12 restituirà solo le proprietà dirette del widget. Un cliente a cui non interessa la trama non deve ottenerlo, e un cliente che si cura può salvare un server colpito ottenendo le informazioni incorporate piuttosto che un semplice collegamento.

In RPC , dovresti utilizzare i parametri di query per circa la stessa cosa: POST /writeEndOfYearCsv?format=csv ti darebbe un rapporto CSV, mentre POST /writeEndOfYearCsv?format=xslx ti darebbe un rapporto Excel.

Il corpo di una richiesta contiene in genere la risorsa che viene creata / modificata (se stai utilizzando un approccio ish REST ) o istruzioni su come elaborare la richiesta (se stai utilizzando un approccio RPC ) . Pertanto, durante la creazione o l'aggiornamento di un widget, la richiesta conterrà tutte le informazioni su cosa costituisce un widget (colori, trama, nome, ecc.). Quando si richiede un rapporto di fine anno, la richiesta può contenere l'anno di richiesta, i client da includere nel rapporto, ecc.

È ancora possibile utilizzare le richieste in stile RPC in un sistema ish REST . Devi solo pensare alla richiesta stessa come a una risorsa. Pertanto, POST /reports/end-of-year con un corpo contenente istruzioni creerebbe un nuovo rapporto e potresti visualizzare GET /reports/end-of-year/9 in seguito per visualizzare quel rapporto.

Se sembra che le richieste in stile RPC offuschino pesantemente le linee in termini di dove "appartengono" le cose, è perché lo fanno. Dato che HTTP è stato progettato attorno a un paradigma "URL-as-resource" e RPC è stato spremuto in cima a questo, è spesso compito dei singoli sviluppatori capire dove è il posto giusto per un'istruzione specifica. Se usi RPC (e in generale, dovresti provare a non farlo), individua una regola generale e sii coerente con il tuo servizio su cosa va dove.

Il corpo di una richiesta o di una risposta dipende in genere dal tipo di richiesta. In REST, il corpo e la risposta sono sempre rappresentazioni di risorse, ma a volte tale risorsa è in realtà un'istruzione. Dovresti

    
risposta data 03.10.2016 - 14:35
fonte
2

API REST su HTTP 1.1

Questi sono (riassumendo) i "principi" che dovremmo considerare se vogliamo essere RESTful-compliant . Tra le altre cose (vedi anche CoRE RFC6690 )

Variabili del percorso

Queste variabili sono usate per   referenziamento delle risorse all'interno di una gerarchia. ( indipendentemente dal metodo )

GET: /app/{appId}/user/{userId} #single resource
GET: /app/{appId}/users #collection
POST: /app/{appId}/user/{userId}
DELETE: /app/{appId}/user/{userId}
...

Variabili di query

Queste variabili sono utilizzate come modificatori della risposta. Per modificatori intendiamo: filtri , paginazione , selezione attributi , ecc.

GET: /app/{appId}/users # all app users

Modifica della risposta:

  GET: /app/{appId}/users?name=Jhon&surname=Conor # Subset by filtering
  GET: /app/{appId}/users?page=1&pageSize=10 # Subset by pagination
  GET: /app/{appId}/users?page=1&pageSize=10&filter=name:jhon;surname:conor # Subset by pagination and filtering

AppId funziona ancora per il riferimento. Fornisce l'ambito / contesto in cui cercare ( utenti dell'app X ). Cambiando questo valore non stiamo modificando la risposta, stiamo cambiando la risorsa.

Queste variabili potrebbero essere usate con PUT, POST, DELETE per eseguire queste azioni su un sottoinsieme di risorse, ma nelle parole dell'OP

I think the use case would be possible in theory but very rare in the practice.

(E ho accettato)

Variabili del corpo

Essendo dogmatici, usiamo il POST per creare nuove risorse e PUT per modificare uno esistente.

Entrambi richiedono un corpo di richiesta, in cui la risorsa da creare / aggiornare è rappresentata nel suo stato finale.

Nota: qui è importante fare riferimento alla loro idempotente natura

POST: /app/{appId}/user
BODY: {"name":"Jhon", "surname":"Conor"}
PUT: /app/{appId}/user/{userId}
BODY: {"name":"Sara", "surname":"Conor"}

Ancora, appId e userId sono semplici variabili di riferimento.

Riassumendo

  • variabili di percorso: per referenziamento (navigazione risorse)
  • query variables: per le modifiche alla risposta
  • Corpo: per la creazione o la modifica delle risorse.

Ecco le specifiche: RFC7230 - RFC7235

Servizi Web SOA su HTTP 1.1

Ho separato SOA WS da RESTful API perché si tratta di 2 diversi design in cui ognuno di essi utilizza le variabili Http citate in un modo diverso.

Questi WS non usano l'URI per il riferimento alle risorse web. Li usano per esporre le procedure .

POST: /app/register
Body:  {"name":"Jhon", "pass":"Conor"}
POST: /app/sendNotification
Body:  {"from":"Jhon", "to":"skynet", text:"see you yesterday"}
POST: /app/markNotificationAsRead
Body:  {"id":"0"}
POST: /app/moveNotifications
Body:  {"from":"inbox", "to":"trash", messages:[]}
GET: /app/notifications?from=Jhon
GET: /app/notifications?if=from:Jhon;to:skynet

In questo approccio, GET e POST sono predominanti.

Le variabili Path e body vengono utilizzate come argomenti della procedura .

Le variabili

Query mantengono la sua funzione di modificatore della risposta .

Le specifiche da implementare dipendono dalle esigenze del sistema. Come ha sottolineato @Eric, ci sono specifiche come RPC che possono essere applicate a questo tipo di servizi Web.

    
risposta data 03.10.2016 - 13:18
fonte

Leggi altre domande sui tag