Files
web/httputil/options.go
T

41 lines
1.6 KiB
Go
Raw Permalink Normal View History

package httputil
import "fmt"
// Option configures a Handle* adapter. With no options each adapter writes its
// default success status (200 for the body-returning adapters, 204 for
// [HandleEmpty]). Options are applied once at wiring time, not per request.
type Option func(*options)
type options struct {
status int
}
// WithStatus overrides the success status an adapter writes — e.g.
// WithStatus(http.StatusCreated) for a POST that creates a resource, or
// WithStatus(http.StatusAccepted) for an async [HandleEmpty].
//
// It exists because the Handle* adapters own only the happy path: they always
// write a success response, so the status is theirs to set, while error statuses
// are derived separately from the returned xerror by [Error]. The code must
// therefore be 2xx — anything else is a routing mistake, since an error status
// never belongs on the success path. WithStatus panics on a non-2xx code, and
// because routes are wired at startup that panic surfaces at boot: the service
// fails to start rather than emitting a wrong status at request time. (mw.Recover
// guards requests, so it does not catch a wiring-time panic — which is the point.)
func WithStatus(code int) Option {
if code < 200 || code > 299 {
panic(fmt.Sprintf("httputil.WithStatus: success status must be 2xx, got %d", code))
}
return func(o *options) { o.status = code }
}
// resolveStatus folds opts over the adapter's default success status.
func resolveStatus(def int, opts []Option) int {
o := options{status: def}
for _, opt := range opts {
opt(&o)
}
return o.status
}