๐ŸŒฌ๏ธ Breeze docs

Context

*breeze.Context is what every handler and middleware receives. It carries the parsed request, the response being built, route params, and a small per-request key/value store.

router.Handle(breeze.GET, "/users/:id", func(ctx *breeze.Context) error {
	id := ctx.Param("id")
	ctx.SetHeader("X-Served-By", "breeze")
	return ctx.JSON(map[string]string{"id": id})
})

Contexts are pooled and reused between requests, which is central to Breeze's low-allocation design โ€” and comes with one rule worth internalizing early: anything read from ctx.Req must be read before ctx.Next() returns control past it, and nothing about the context should be retained past the handler returning. Strings on the request point into a pooled read buffer the next request on that connection reuses.

Writing a response

MethodBehaviour
ctx.JSON(data any) errormarshals with go-json, sets Content-Type: application/json
ctx.HTML(data []byte) errorwrites raw bytes with Content-Type: text/html
ctx.WriteString(s string) errorwrites a plain-text body
ctx.Status(code int)sets the response status
ctx.SetHeader(key, value string)sets a response header
ctx.GetHeader(key string) stringreads a request header

A Content-Type set explicitly with SetHeader before a body method wins over that method's default โ€” this is what makes application/problem+json possible from ctx.JSON. A previous body method's content type does not win: ctx.WriteString(...) followed by ctx.JSON(...) sends application/json, not text/plain. Only a type set through SetHeader is treated as a deliberate choice.

Set response headers before Next(), not after. A middleware that calls ctx.SetHeader after ctx.Next() returns is too late โ€” the handler has already written the response. This bit real code once: see the ordering notes in Middleware Reference.

Params, query, and the store

ctx.Param("id")             // route param, e.g. /users/:id
ctx.Query("page")           // query string value
ctx.GetParams()             // map[string]string, every route param

ctx.Set("user", user)       // per-request key/value store
user, ok := ctx.Get("user")
mustUser := ctx.MustGet("user") // panics if absent

Binding and validation

type CreateUser struct {
	Name  string `json:"name"  validate:"required,min=2,max=50"`
	Email string `json:"email" validate:"required,email"`
	ID    string `param:"id"`
}

router.Handle(breeze.POST, "/users/:id", func(ctx *breeze.Context) error {
	var in CreateUser
	if err := ctx.Bind(&in); err != nil {
		return nil // the 422 problem+json response is already written
	}
	return ctx.JSON(in)
})

ctx.Bind decodes the JSON body, query, form, and path params into one struct and validates it in a single call โ€” see Request Binding & Validation for the full source order and rule set.

Chain control

func requireAPIKey(ctx *breeze.Context) error {
	if ctx.GetHeader("x-api-key") != wantKey {
		ctx.Status(401)
		return ctx.JSON(map[string]string{"error": "api key required"})
	}
	return ctx.Next()
}

ctx.Next() runs the next middleware or the handler in the chain and returns its error. ctx.Abort() stops the chain without running the rest โ€” a middleware that doesn't call Next() simply ends the request there.

Errors

A handler returns an error; one function decides what that becomes on the wire. See Errors as Values.

Generated documentation for the Breeze framework ยท built with SvelteKit, fully static.