HTTP Transport Mapping
Payload to HTTP request mapping
Il tipo Payload descrive la forma dei dati in argomento ai service methods. Il DSL per il protocollo HTTP definisce come i dati vengono costruiti a partire dallo stato delle richieste HTTP in arrivo.
Lo stato della richiesta HTTP comprende quattro parti differenti:
- Gli URL path parameters (per esempio la route
/bottle/{id}
definisce il path parameterid
) - I parametri all’interno della querystring
- Gli header HTTP
- Il body della richiesta HTTP
La espressione HTTP generata guida la decodifica della richiesta all’interno del payload:
- L’espressione
Param
definisce i parametri caricati da path o query string. - L’espressione
Header
definisce i parametri corrispondenti a valor negli header HTTP. - L’espressione
Body
definisce i valori all’interno del corpo della richiesta.
Le due sezioni successive descrivono queste espressioni in maggior dettaglio.
Nota che nel codice generato fornisce un decoder di default che dovrebbe essere sufficiente nella maggior parte dei casi, tuttavia rende anche possibile di integrare un decoder personalizzato nei (si spera rari) casi in cui questo sia richiesto.
Mapping del payload con tipi non-object
Quando il tipo del payload è un tipo primitivo (ad esempio uno fra String, un qualunque tipo di Integer o Float, Boolean o Bytes), oppure un array o una map il valore è caricato da:
- il primo URL path parameter definito nel design, se presente, altrimenti
- il primo parametro nella query string definito nel design, se presente, altrimenti
- il primo header definito nel design, se presente, altrimenti
- il body della richiesta.
con le seguenti restrizioni:
- solo i tipi primitivi o gli array possono essere usati per definire header o path parameters.
- solo primitive, array e map possono essere usati per definire i parametri nella query string.
- I tipi array e map usati per definire path parameters, headers o parametri nella query string devono usare i tipi primitivi per definire i loro elementi.
Gli array nei path parameters e negli header sono rappresentati come valori separati da virgole.
Esempi:
- un semplice “get by identifier” dove gli identifiers sono interi:
Method("show", func() {
Payload(Int)
HTTP(func() {
GET("/{id}")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Show(int) | GET /1 | Show(1) |
- “delete by identifiers” in blocco dove gli identifiers sono stringhe:
Method("delete", func() {
Payload(ArrayOf(String))
HTTP(func() {
DELETE("/{ids}")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Delete([]string) | DELETE /a,b | Delete([]string{“a”, “b”}) |
Nota che in entrambi gli esempi precedenti il nome del path parameter non è rilevante.
- array in query string:
Method("list", func() {
Payload(ArrayOf(String))
HTTP(func() {
GET("")
Param("filter")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
List([]string) | GET /?filter=a&filter=b | List([]string{“a”, “b”}) |
- float in header:
Method("list", func() {
Payload(Float32)
HTTP(func() {
GET("")
Header("version")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
List(float32) | GET / [version=1.0] | List(1.0) |
- map in body:
Method("create", func() {
Payload(MapOf(String, Int))
HTTP(func() {
POST("")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Create(map[string]int) | POST / {“a”: 1, “b”: 2} | Create(map[string]int{“a”: 1, “b”: 2}) |
Mapping del payload con object types
L’espressione HTTP descrive come gli attributi del payload sono caricati dallo stato della richiesta HTTP. Attributi differenti possono essere caricati da parti differenti della richiesta: alcuni attributi possono essere caricati dalla request path, dalla query string o dagli header e altri dal body, per esempio. Lo stesso tipo di restrizioni si applica ad attributi da path, query string e header (gli attributi che descrivono path parameters o parametri della query string o headers devono essere tipi primitivi, array o map di primitivi).
L’espressione Body
rende possibile definire il tipo all’interno del payload che
descrive il bosy della richiesta. In alternativa se l’espressione Body
è omessa
allora tutti gli attributi che compongono il payload e non sono usati a definire
un path parameter, un parametro della query string o un header implicitamente
descrive il body.
Per esempio, dato il seguente payload:
Method("create", func() {
Payload(func() {
Attribute("id", Int)
Attribute("name", String)
Attribute("age", Int)
})
})
La seguente espressione HTTP fa in modo che l’attributo id
venga caricato dal
path parameter mentre name
e age
sono caricati dal request body:
Method("create", func() {
Payload(func() {
Attribute("id", Int)
Attribute("name", String)
Attribute("age", Int)
})
HTTP(func() {
POST("/{id}")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Create(*CreatePayload) | POST /1 {“name”: “a”, “age”: 2} | Create(&CreatePayload{ID: 1, Name: “a”, Age: 2}) |
Body
ammette elementi che non sono necessariamente primitivi o objects, come array e map.
Prendiamo ad esempio il seguente payload:
Method("rate", func() {
Payload(func() {
Attribute("id", Int)
Attribute("rates", MapOf(String, Float64))
})
})
Usando la seguente espressione HTTP il parametro rates
è caricato dal body:
Method("rate", func() {
Payload(func() {
Attribute("id", Int)
Attribute("rates", MapOf(String, Float64))
})
HTTP(func() {
PUT("/{id}")
Body("rates")
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Rate(*RatePayload) | PUT /1 {“a”: 0.5, “b”: 1.0} | Rate(&RatePayload{ID: 1, Rates: map[string]float64{“a”: 0.5, “b”: 1.0}}) |
Senza Body
la forma del body sarebbe un oggeto con un unico campo rates
.
Mapping HTTP di elementi ad attributi
Le espressioni come Param
, Header
e Body
, potrebbero avere un mapping
fra i nomi degli elementi (query string key, nome di un header o di un campo del
body) e il corrispondente attributo all’interno del payload.
Il mapping è definito usando la sintassi "attribute name:element name"
,
ad esempio:
Header("version:X-Api-Version")
L’espressione qui in alto fa in modo che l’attributo version
venga
caricato dall’header HTTP X-Api-Version
.
L’espressione Body
supporta una sintassi alternativa dove gli attributi che compaiono
nel body vengano listati esplicitamente. Tale sintassi permette di specificare un mapping
fra nomi dei campi e i nomi degli attributi nel payload,
ad esempio:
Method("create", func() {
Payload(func() {
Attribute("name", String)
Attribute("age", Int)
})
HTTP(func() {
POST("")
Body(func() {
Attribute("name:n")
Attribute("age:a")
})
})
})
Metodo Generato | Richiesta di esempio | Chiamata corrispondente |
---|---|---|
Create(*CreatePayload) | POST /1 {“n”: “a”, “a”: 2} | Create(&CreatePayload{ID: 1, Name: “a”, Age: 2}) |