Body parser
This guide covers reading request bodies in Tinka. You will learn how to:
- Decode a JSON request body into a typed value
- Validate the input and report every invalid field at once
- Know which status each failure returns, and the limits that protect the server
Overview
tinka.Decode reads a JSON request body into a value of the type you name, checks it with your validation, and turns every failure into a response the client can act on. It also guards the server: bodies are capped at 1 MiB and must arrive within 30s, so a client cannot exhaust memory or hold a request open.
Decode a body
Name the type you expect and pass the response writer and the request. On failure, return the error: it's already the right response.
package main
import (
"net/http"
"github.com/mucolabs/tinka"
)
type newPost struct {
Title string `json:"title"`
Body string `json:"body"`
}
func createPost(w http.ResponseWriter, r *http.Request) error {
in, err := tinka.Decode[newPost](w, r)
if err != nil {
return err
}
return tinka.JSON(w, http.StatusCreated, in)
}Decode answers with these statuses, each as problem details:
- 415: the
Content-Typeisn't JSON (application/jsonor a+jsontype) - 400: the body is empty, malformed, or holds more than one JSON value
- 413: the body is larger than 1 MiB (
tinka.MaxBodyBytes) - 408: the body took longer than 30s to arrive
- 422: a field has the wrong type, or your validation found problems
Validate the input
Give the type a Valid method and Decode calls it after decoding. It returns a problem for each invalid field, keyed by the field's name; an empty map means the input is valid. Add context and strings to the file's imports, then the method:
func (p newPost) Valid(ctx context.Context) map[string]string {
problems := map[string]string{}
if strings.TrimSpace(p.Title) == "" {
problems["title"] = "Enter a title."
}
if len(p.Body) > 10_000 {
problems["body"] = "Keep the body under 10,000 characters."
}
return problems
}Every invalid field comes back in one 422 response, so a form can show all its errors at once:
{
"title": "Unprocessable Entity",
"status": 422,
"detail": "Some fields are invalid.",
"code": "invalid",
"fields": {
"title": "Enter a title."
},
"request_id": "S5QWQ3DAEXTVZ6M7F4DZEL6EBI"
}See also: Exception handling, App