HTTP Style and Syntax
http.Join(arrows ...http.Arrow) assay.Arrow
builds higher-order HTTP closure, so called assay.Arrow
, from primitive elements.
http.Join(
ø.GET("https://assay.it"),
ƒ.Code(http.StatusCodeOK),
ƒ.Header("Content-Type").Is("text/html"),
)
Let’s look on these primitives:
Imports
Any suite requires at least these three modules:
import (
"github.com/assay-it/sdk-go/http"
ƒ "github.com/assay-it/sdk-go/http/recv"
ø "github.com/assay-it/sdk-go/http/send"
)
Writer
Writer morphism (Symbol ø) focuses inside and reshapes HTTP protocol request. The writer morphism is used to declare HTTP method, destination URL, request headers and payload.
Method & URL
Like any HTTP request, you have to define method and destination URL:
// built-in method
ø.GET("http://example.com")
ø.POST("http://example.com")
ø.PUT("http://example.com")
ø.DELETE("http://example.com")
// generic variant
ø.URL("PATCH", "http://example.com")
These functions are able to format URL according to standard specifiers.
ø.GET("http://example.com/%s/%d", "test", 10)
lit := "test"
ø.GET("http://example.com/%s", lit)
ø.GET("http://example.com/%s", &lit)
Important Formatted values are escaped using percent encoding.
// this ok
ø.GET("https://%s/%s", "example.com", "test")
// this do not work
ø.GET("https://%s", "example.com/test")
Query Params
It is possible to use inline query parameters but it is not a type safe approach:
ø.GET("http://example.com/?tag=%s", "test")
The SDK implement an arrow ø.Params
. It takes a struct serializes it to string and appends query params. You are able to define proper types for your api:
type MyParam struct {
Site string `json:"site,omitempty"`
Host string `json:"host,omitempty"`
}
ø.Params(MyParam{Site: "site", Host: "host"})
Headers
Headers are optional, you define as many headers as needed either using string literals or state variables.
// the literal value is defined using Is
ø.Header("Accept").Is("application/json")
// the header value is defined from state variable
ø.Header("Authorization").Val(&token)
Important There are header constants for frequently used headers.
Request payload
ø.Send
transmits the payload to destination URL. The function takes Go data types (e.g. maps, struct, etc) and encodes its to binary using Content-Type as a hint. The function fails if content type is not supported by the library.
type MyType struct {
Site string `json:"site,omitempty"`
Host string `json:"host,omitempty"`
}
ø.Send(MyType{Site: "site", Host: "host"})
ø.Send(map[string]string{
"site": "site",
"host": "host",
})
Only following content types supported:
application/json
application/x-www-form-urlencoded
Reader
Reader morphism (Symbol ƒ) focuses into side-effect, HTTP protocol response. The reader morphism is a pattern matcher, is used to match HTTP response code, headers and response payload.
Status Code
Each quality assessment have to declare expected status code(s). The primitive ƒ.Code
takes one or few HTTP Status Codes. The assessment fails if microservice responds with other status.
ƒ.Code(http.StatusCodeOK)
Headers
It is possible to match value of HTTP header in the response. The assessment fails if response is missing header or its value do not matches desired one:
// matches Content-Type value
ƒ.Header("Content-Type").Is("application/json")
// matches any value of Content-Type header
ƒ.Header("Content-Type").Is("*")
ƒ.Header("Content-Type").Any()
The assessment statements can lifts the header value to the variable.
var content string
ƒ.Header("Content-Type").String(&content)
Response payload
ƒ.Recv
decodes the response payload to Golang native data structure using Content-Type header as a hint.
type MyType struct {
Site string `json:"site,omitempty"`
Host string `json:"host,omitempty"`
}
var data MyType
ƒ.Recv(&data)
The codec only supports:
application/json
application/x-www-form-urlencoded
It is possible to bypass auto-codec and receive raw binary data
var data []byte
ƒ.Bytes(&data)