Responses and Rendering
Zinc provides response helpers for common API and web application flows.
At a glance
Section titled “At a glance”return c. Status(zinc.StatusCreated). SetHeader(zinc.HeaderLocation, "/users/42"). JSON(zinc.Map{"id": 42})Set status and headers before writing the body. Once a response helper writes, treat the response as complete.
Plain responses
Section titled “Plain responses”return c.String("ok")return c.HTML("<strong>ok</strong>")return c.NoContent()Structured responses
Section titled “Structured responses”return c.JSON(zinc.Map{"ok": true})return c.XML(payload)return c.YAML(payload)return c.TOML(payload)For pretty JSON:
return c.JSONPretty(payload, " ")If you already have encoded bytes:
return c.JSONBlob(zinc.StatusOK, rawJSON)return c.XMLBlob(zinc.StatusOK, rawXML)return c.HTMLBlob(zinc.StatusOK, rawHTML)return c.Blob(zinc.StatusOK, "application/custom", payload)Blob helpers write the bytes you pass in. They do not re-encode the payload.
Status and headers
Section titled “Status and headers”Use the response builder style when you want to set headers or status before writing the body.
return c. Status(zinc.StatusCreated). SetHeader(zinc.HeaderLocation, "/users/42"). JSON(zinc.Map{"id": 42})Useful helpers include:
Status(code)SetHeader(key, value)AppendHeader(key, values...)Type(ext)Location(url)Vary(fields...)SetSameSite(mode)
For cookies:
c.SetSameSite(http.SameSiteLaxMode)c.SetCookie(&http.Cookie{Name: "session", Value: token, Path: "/"})Redirects
Section titled “Redirects”return c.Redirect(zinc.StatusTemporaryRedirect, "/login")Templates
Section titled “Templates”Configure a renderer in Config and then call Render.
views := template.Must(template.ParseGlob("templates/*.html"))
app := zinc.NewWithConfig(zinc.Config{ Renderer: zinc.NewHTMLTemplateRenderer(views),})
app.Get("/dashboard", func(c *zinc.Context) error { return c.Render("dashboard.html", zinc.Map{"Title": "Overview"})})Files and downloads
Section titled “Files and downloads”Serve files directly from disk or an fs.FS.
return c.File("./public/report.pdf")return c.FileFS("report.pdf", embeddedFiles)For downloads and attachments:
return c.Download("./exports/users.csv", "users-latest.csv")return c.Inline("./public/report.pdf")Streams
Section titled “Streams”reader := strings.NewReader("streamed content")return c.Stream("text/plain; charset=utf-8", reader)For server-sent events, write one event at a time:
app.Get("/events", func(c *zinc.Context) error { for _, msg := range messages { if err := c.SSE(zinc.SSEvent{ Event: "message", Data: zinc.Map{"text": msg}, }); err != nil { return err } if flusher, ok := c.Writer().(http.Flusher); ok { flusher.Flush() } } return nil})SSE writes one event and leaves streaming control with the handler.
Content negotiation
Section titled “Content negotiation”Use Accepts when the handler needs to branch before writing.
switch c.Accepts("application/json", "text/html") {case "application/json": return c.JSON(payload)case "text/html": return c.Render("users/show", payload)default: return zinc.ErrNotAcceptable}Use Negotiate when the response body can be offered in multiple content types.
return c.Negotiate(zinc.StatusOK, zinc.Map{ "application/json": zinc.Map{"ok": true}, "text/plain": "ok",})Accepts follows the request Accept header, including quality values and type/* or */* wildcards. When no Accept header is present, Zinc picks the first offered type.
Response writer wrapping
Section titled “Response writer wrapping”Middleware that needs response status or byte counts can wrap the underlying writer.
base := c.Writer()rw := zinc.WrapResponseWriter(base)c.SetWriter(rw)defer c.SetWriter(base)WrapResponseWriter returns zinc.ResponseWriter.
type ResponseWriter interface { http.ResponseWriter Status() int BytesWritten() int Written() bool}It preserves common optional writer behavior such as flushing, hijacking, io.ReaderFrom, server push, and unwrapping when the underlying writer supports it.
Good API pattern
Section titled “Good API pattern”For API handlers, prefer one clear return path: validate input, run application logic, then return one response helper or one error.
app.Post("/users", func(c *zinc.Context) error { var input CreateUserInput if err := c.Bind().JSON(&input); err != nil { return err }
user, err := createUser(input) if err != nil { return err }
return c.Status(zinc.StatusCreated).JSON(user)})See also
Section titled “See also”- Errors for error responses.
- Configuration for custom renderers and JSON codecs.
- Context API for response helper details.
