Body Parser
Nimbus handlers have full access to the underlying *http.Request via c.Request. You parse request bodies using Go's standard library — there is no magic, just familiar patterns.
Parsing JSON bodies
Use encoding/json to decode the request body into a struct or map. The body is available at c.Request.Body.
type CreateUserInput struct {
Name string
Email string
}
func createUser(c *http.Context) error {
var input CreateUserInput
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
return c.JSON(400, map[string]string{"error": "invalid json"})
}
defer c.Request.Body.Close()
return c.JSON(201, map[string]string{
"name": input.Name,
"email": input.Email,
})
}
Parsing form data
For application/x-www-form-urlencoded bodies (standard HTML forms), call c.Request.ParseForm() then read values with c.Request.FormValue(key).
func handleForm(c *http.Context) error {
if err := c.Request.ParseForm(); err != nil {
return c.JSON(400, map[string]string{"error": "bad form data"})
}
name := c.Request.FormValue("name")
email := c.Request.FormValue("email")
return c.JSON(200, map[string]string{
"name": name,
"email": email,
})
}
Parsing multipart form data
For multipart/form-data (file uploads and mixed fields), call c.Request.ParseMultipartForm(maxMemory). The maxMemory parameter controls how much is buffered in memory (excess goes to temp files).
func handleMultipart(c *http.Context) error {
// 10 MB max in memory
if err := c.Request.ParseMultipartForm(10 << 20); err != nil {
return c.JSON(400, map[string]string{"error": "bad multipart data"})
}
title := c.Request.FormValue("title")
description := c.Request.FormValue("description")
return c.JSON(200, map[string]string{
"title": title,
"description": description,
})
}
Binding JSON to a struct
A common pattern is to define a request struct and a helper function that decodes and validates in one step.
func bindJSON(r *http.Request, dest any) error {
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
return decoder.Decode(dest)
}
type UpdatePostInput struct {
Title string
Content string
}
func updatePost(c *http.Context) error {
var input UpdatePostInput
if err := bindJSON(c.Request, &input); err != nil {
return c.JSON(400, map[string]string{"error": err.Error()})
}
return c.JSON(200, input)
}
Content-Type detection
Check the Content-Type header to decide how to parse the body. This lets a single handler accept both JSON and form data.
func flexibleHandler(c *http.Context) error {
ct := c.Request.Header.Get("Content-Type")
switch {
case strings.HasPrefix(ct, "application/json"):
var data map[string]any
json.NewDecoder(c.Request.Body).Decode(&data)
return c.JSON(200, data)
case strings.HasPrefix(ct, "application/x-www-form-urlencoded"):
c.Request.ParseForm()
return c.JSON(200, map[string]string{
"name": c.Request.FormValue("name"),
})
default:
return c.JSON(415, map[string]string{
"error": "unsupported content type",
})
}
}
Tips
- Always close or drain
c.Request.Bodyto avoid resource leaks. - Use
io.LimitReaderto cap body size before decoding for safety. - Use
decoder.DisallowUnknownFields()to reject unexpected JSON keys. - For validation after parsing, see the Validation docs.