Response

Every Nimbus handler receives a *http.Context (aliased as c) which provides convenient helpers for sending HTTP responses. Under the hood, c.Response is a standard http.ResponseWriter, so all Go idioms work too.

JSON responses

Send a JSON body with a status code. The Content-Type header is set to application/json automatically.

func listUsers(c *http.Context) error {
    users := []map[string]string{
        {"name": "Alice"},
        {"name": "Bob"},
    }
    return c.JSON(200, users)
}

func createUser(c *http.Context) error {
    return c.JSON(201, map[string]string{"message": "created"})
}

Plain text responses

Send a plain text response with c.String(code, text). Content-Type is set to text/plain; charset=utf-8.

func healthCheck(c *http.Context) error {
    c.String(200, "OK")
    return nil
}

Rendering views

Render a .nimbus template and send it as HTML. Pass a data map that becomes available in the template.

func homePage(c *http.Context) error {
    return c.View("home", map[string]any{
        "title": "Welcome",
        "name":  "Guest",
    })
}

Redirects

Issue an HTTP redirect with c.Redirect(code, url). Common codes are 301 (permanent) and 302 (temporary).

func oldPage(c *http.Context) error {
    c.Redirect(301, "/new-page")
    return nil
}

func afterLogin(c *http.Context) error {
    c.Redirect(302, "/dashboard")
    return nil
}

Setting status code

Use c.Status(code) to write the status header directly. This is useful when you want to set the status before writing the body yourself.

func noContent(c *http.Context) error {
    c.Status(204)
    return nil
}

Setting response headers

Access the underlying http.ResponseWriter via c.Response to set custom headers. Headers must be set before calling WriteHeader or writing the body.

func customHeaders(c *http.Context) error {
    c.Response.Header().Set("X-Request-Id", "abc-123")
    c.Response.Header().Set("Cache-Control", "no-cache")
    return c.JSON(200, map[string]string{"ok": "true"})
}

Writing raw bytes

For full control, write directly to c.Response. It implements http.ResponseWriter, so you can call Write([]byte) directly.

func rawResponse(c *http.Context) error {
    c.Response.Header().Set("Content-Type", "application/octet-stream")
    c.Response.WriteHeader(200)
    _, err := c.Response.Write([]byte("raw bytes here"))
    return err
}

Streaming responses

Since c.Response is an http.ResponseWriter, you can flush chunks for streaming. If the writer supports http.Flusher, call Flush() after each write.

func streamHandler(c *http.Context) error {
    c.Response.Header().Set("Content-Type", "text/event-stream")
    c.Response.Header().Set("Cache-Control", "no-cache")
    c.Response.WriteHeader(200)

    flusher, ok := c.Response.(http.Flusher)
    if !ok {
        return fmt.Errorf("streaming not supported")
    }

    for i := 0; i < 5; i++ {
        fmt.Fprintf(c.Response, "data: message %d\n\n", i)
        flusher.Flush()
        time.Sleep(1 * time.Second)
    }
    return nil
}

Response helper summary

  • c.JSON(code, body) — Send JSON with status code.
  • c.String(code, text) — Send plain text.
  • c.View(name, data) — Render a .nimbus template as HTML.
  • c.Redirect(code, url) — Send an HTTP redirect.
  • c.Status(code) — Write the status header (returns *Context for chaining).
  • c.Response — The underlying http.ResponseWriter for raw access.