Documentation
¶
Overview ¶
Package rest provides a REST API transport.
var API struct { api.Specification `rest:"http://api.example.com/v1"` Echo func(message string) string `rest:"GET /echo?message=%v"` }
When Echo is called, it calls the function over HTTPS/REST to 'https://api.example.com/v1/echo' and returns the result (if there is an error and the function doesn't return one, it will panic).
The REST transport will be served by the api.Handler when the Content-Type of the request is 'application/json' and the API has suitable rest tags.
API.Echo = func(message string) string { return message } api.ListenAndServe(":"+os.Getenv("PORT"), &API)
This starts a local HTTP server and listens on PORT for requests to /echo and responds to these requests with the defined Echo function. Arguments and Results are automatically converted to the Content-Type where possible.
You can return receive-only channels which will be served to clients as a websocket.
Tags ¶
Each API function can have a rest tag that formats function arguments (%v) to query parameters. Each tag must follow the space-seperated pattern:
GET /path/to/endpoint/{object=%v}?query=%v (argument,mapping,rules) result,mapping,rules [METHOD](CONTENT_TYPE) [PATH] (ARGUMENT_RULES) RESULT_RULES
It begins with a METHOD, followed by an optional body CONTENT_TYPE then with a PATH format string that descibes how the function arguments are mapped onto the HTTP path & query. This is an extension of http.ServeMux with support for fmt rules and content types.
The CONTENT_TYPE (when unspecified) defaults to:
- text/plain for booleans, numerical values, time.Time, []byte and strings.
- application/json for structs, arrays, slices and maps.
The path can contain path expansion parameters {name=%v} or ordinary format parameters %v (similar to the fmt package). Think of the arguments of the function as the parameters that get passed to a printf call. Imagine it working like this:
http.Get(fmt.Sprintf("/path/with/%v?query=%v", value, query))
If the query parameter is untitled, then the value will be expanded as key-value query parameters. This applies to structs and maps:
GET /path/to/endpoint?%v
If a path or query expansion parameter omits a format parameter, the value will be considered to be nested within a struct argument and the name of the parameter will be used to look for the first matching field in subsequent body structures. Either by field name or by rest tag.
POST /path/to/endpoint/{ID} { ID: "1234", Value: "something" }
If a path expansion parameter is suffixed with an asterisk, then no escape will be performed on the value, ie. slashes will be added to the path as-is.
POST /prefix/{path*=%v}
ARGUMENT_RULES are optional, they are a comma separated list of names to give the remaining arguments in the JSON body of the request. By default, arguments are posted as an array, however if there are ARGUMENT_RULES, the arguments will be mapped into json fields of the name, matching the argument's position.
foo func(id int, value string) `rest:"POST /foo (id,value)"` foo(22, "Hello World") => {"id": 22, "value":"Hello World"}
RESULT_RULES are much like ARGUMENT_RULES, except they operate on the results of the function instead of the arguments. They map named json fields to the result values.
getLatLong func() (float64, float64) `rest:"GET /latlong latitude,longitude"` {"latitude": 12.2, "longitude": 15.0} => lat, lon := getLatLong()
Response Headers ¶
In order to read and write HTTP headers in a request, values should implement the following interfaces.
type HeaderWriter interface { WriteHeadersHTTP(http.Header) } type HeaderReader interface { ReadHeadersHTTP(http.Header) }
If multiple result values implement these interfaces, they will be called in the order they are returned. Here's an example:
type ProfilePicture struct { io.ReadCloser } func (ProfilePicture) WriteHeadersHTTP(header http.Header) { header.Set("Content-Type", "image/png") } type API struct { api.Specification GetProfilePicture func() (ProfilePicture, error) }
Index ¶
Constants ¶
This section is empty.
Variables ¶
API implements the api.Linker interface.
Functions ¶
Types ¶
type RequestWriter ¶
func (RequestWriter) Header ¶
func (w RequestWriter) Header() http.Header
func (RequestWriter) WriteHeader ¶
func (w RequestWriter) WriteHeader(status int)