Go REST endpoints#
The Go generator can make a REST API for each top_level struct. The
endpoints use the postgres feature, so you must also
enable that feature. Enable the endpoints in model.toml:
[tool.model.go]
out = "output.go"
package = "mypkg"
[tool.model.go.features]
postgres = 1
[tool.model.go.rest]
base-path = "/api"
base-path must start with /. The generator removes a trailing /.
Endpoints#
The path segment of a struct is its name in kebab-case. For example,
SaveRecord becomes save-record. A struct T with the segment t gets
these endpoints:
Request |
Operation |
Success |
|---|---|---|
|
Creates a row from the body. |
|
|
Reads the row. |
|
|
Replaces a row that exists. It does not create a row. |
|
|
Applies a JSON Merge Patch (RFC 7386). |
|
|
Deletes the row. |
|
{id} is the value of the struct’s primary key. These conditions apply to
the struct:
It must have exactly one
primary_keyfield.The key must be a
string, aninteger, or an enum. An enum key uses the name of the enum value.
If a struct does not meet these conditions, generation fails. Generation also fails in these conditions:
Two structs have the same path segment.
A model route uses the same method and path as an endpoint.
Register the endpoints on a mux. The handlers use the request transaction, so
DBMiddleware must wrap the mux:
mux := http.NewServeMux()
genmodel.RegisterRestEndpoints(mux)
genmodel.RegisterAllEndpoints(mux) // only if the model has routes
return http.ListenAndServe(":8080", genmodel.DBMiddleware(pool)(mux))
Each handler commits or rolls back the transaction before it writes the response. If the commit fails, the client gets status 500.
Bodies#
Request and response bodies are JSON. If you enable the yaml feature, a
request with a YAML Content-Type is read as YAML. A request whose Accept
header prefers YAML gets a YAML response.
PATCH accepts only application/merge-patch+json or application/json.
For other content types, the response is 415 with an Accept-Patch header.
The patch is applied to the JSON form of the row. The result is then decoded
and validated. A patch cannot change the primary key.
Errors#
Errors are application/problem+json bodies
(RFC 9457) with title, status,
and detail. A validation failure also lists each failed constraint in
errors, with kind, path, and message.
PUT and PATCH accept a row that fails validation if it adds no
violations to the stored row. For the rule, see
stored rows that fail validation.
If the row adds violations, the response is 422:
errorslists only the new violations.existing_errorslists all the violations of the stored row. It has the same form aserrors.
Other validation failures do not have existing_errors.
{
"title": "Unprocessable Entity",
"status": 422,
"detail": "the update adds violations the stored value does not have: note: must have no more than 5 characters",
"errors": [{"kind": "length", "path": "note", "message": "must have no more than 5 characters"}],
"existing_errors": [{"kind": "range", "path": "id", "message": "must be no less than 1"}]
}
Status |
Cause |
|---|---|
|
The body or the |
|
The row does not exist. |
|
The row already exists ( |
|
A precondition failed. |
|
A |
|
The row fails |
|
Any other failure. The detail is logged and not sent, except |