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 }