41 lines
1.6 KiB
Go
41 lines
1.6 KiB
Go
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
|
|
}
|