This section explains how service method payloads are mapped to HTTP endpoints using the HTTP transport DSL. The payload types define the shape of the data passed as arguments to service methods, while the HTTP expressions specify how to build this data from various parts of an incoming HTTP request.
An HTTP request is composed of four parts:
URL Path Parameters
For example, in the route /bottle/{id}
, the {id}
is a path parameter.
URL Query String Parameters
HTTP Headers
HTTP Request Body
The HTTP expressions guide how the generated code decodes the request into the expected payload:
Param
Expression: Loads values from path or query string parameters.Header
Expression: Loads values from HTTP headers.Body
Expression: Loads values from the request body.The next sections describe these expressions in more detail.
When the payload type is a primitive (e.g. String
, integer types, Float
,
Boolean
, or Bytes
), an array, or a map, the value is loaded from the first
defined element in the following order:
Method("show", func() {
Payload(Int)
HTTP(func() {
GET("/{id}")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Show(int) | GET /1 | Show(1) |
Method("delete", func() {
Payload(ArrayOf(String))
HTTP(func() {
DELETE("/{ids}")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Delete([]string) | DELETE /a,b | Delete([]string{"a", "b"}) |
Note: The actual name of the path parameter is not significant.
Method("list", func() {
Payload(ArrayOf(String))
HTTP(func() {
GET("")
Param("filter")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
List([]string) | GET /?filter=a&filter=b | List([]string{"a", "b"}) |
Method("list", func() {
Payload(Float32)
HTTP(func() {
GET("")
Header("version")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
List(float32) | GET / with header version=1.0 | List(1.0) |
Method("create", func() {
Payload(MapOf(String, Int))
HTTP(func() {
POST("")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Create(map[string]int) | POST / {"a": 1, "b": 2} | Create(map[string]int{"a": 1, "b": 2}) |
For payloads defined as objects (with multiple attributes), HTTP expressions allow you to specify where each attribute is loaded from. Some attributes can come from the URL path, others from query parameters, headers, or the body. The same type restrictions apply:
Body
ExpressionThe Body
expression specifies which payload attribute corresponds to the HTTP
request body. If you omit the Body
expression, any attributes not mapped to a
path, query, or header are automatically assumed to come from the body.
Given the payload:
Method("create", func() {
Payload(func() {
Attribute("id", Int)
Attribute("name", String)
Attribute("age", Int)
})
})
The following HTTP expression maps the id
attribute to a path parameter and the remaining attributes to the request body:
Method("create", func() {
Payload(func() {
Attribute("id", Int)
Attribute("name", String)
Attribute("age", Int)
})
HTTP(func() {
POST("/{id}")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Create(*CreatePayload) | POST /1 {"name": "a", "age": 2} | Create(&CreatePayload{ID: 1, Name: "a", Age: 2}) |
Body
for Non-Object TypesThe Body
expression also supports cases where the request body is not an object (for example, an array or a map).
Consider the following payload:
Method("rate", func() {
Payload(func() {
Attribute("id", Int)
Attribute("rates", MapOf(String, Float64))
})
})
Using the HTTP expression below, the rates
attribute is loaded directly from the body:
Method("rate", func() {
Payload(func() {
Attribute("id", Int)
Attribute("rates", MapOf(String, Float64))
})
HTTP(func() {
PUT("/{id}")
Body("rates")
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Rate(*RatePayload) | PUT /1 {"a": 0.5, "b": 1.0} | Rate(&RatePayload{ID: 1, Rates: map[string]float64{"a": 0.5, "b": 1.0}}) |
Without the Body
expression, the request body would be interpreted as an object with a single field named rates
.
The expressions Param
, Header
, and Body
allow you to map HTTP element
names (e.g., query string keys, header names, or body field names) to payload
attribute names. The mapping syntax is:
"attribute name:element name"
For example:
Header("version:X-Api-Version")
In this case, the version
attribute will be loaded from the X-Api-Version
HTTP header.
The Body
expression also supports an alternative syntax that explicitly lists
the body attributes and their corresponding HTTP field names. This is useful for
specifying a mapping between incoming field names and payload attribute names.
Method("create", func() {
Payload(func() {
Attribute("name", String)
Attribute("age", Int)
})
HTTP(func() {
POST("")
Body(func() {
Attribute("name:n")
Attribute("age:a")
})
})
})
Generated method | Example request | Corresponding call |
---|---|---|
Create(*CreatePayload) | POST / {"n": "a", "a": 2} | Create(&CreatePayload{Name: "a", Age: 2}) |
This guide should help you map your service methods to HTTP endpoints effectively, providing clear instructions on how to extract and map the different parts of an HTTP request to your service payloads.