Documentation
¶
Overview ¶
Package api provides the HTTP server and routing for the Berth API server.
The package exposes a TLS-only Server that wraps net/http.Server with graceful shutdown and functional options for configuration. Routes are registered via NewMux, which returns an net/http.ServeMux with the current API endpoints.
Server Lifecycle ¶
Create a server with NewServer, configure it with Option functions, and run it with Server.Start:
srv := api.NewServer(
api.WithAddress(":8443"),
api.WithTLSFiles("/path/to/cert.pem", "/path/to/key.pem"),
api.WithHandler(api.NewMux()),
)
err := srv.Start(ctx)
The server blocks until the context is canceled, then drains in-flight requests before returning.
Middleware ¶
ChainMiddleware composes multiple HTTP middleware functions in left-to-right order around a base handler.
Index ¶
- func AuthMiddleware(authn auth.Authenticator) func(http.Handler) http.Handler
- func ChainMiddleware(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler
- func IdentityFromContext(ctx context.Context) *auth.Identity
- func LoggingMiddleware(logger *slog.Logger) func(http.Handler) http.Handler
- func MetricsMiddleware(m RequestMetrics) func(http.Handler) http.Handler
- func NewMux(mgr LeaseManager, authn auth.Authenticator, authz tenant.Authorizer) *http.ServeMux
- func RequestIDFromContext(ctx context.Context) string
- func WithIdentity(ctx context.Context, id *auth.Identity) context.Context
- type AcquireRequest
- type LeaseManager
- type LeaseResponse
- type Option
- type ReadinessChecker
- type ReleaseRequest
- type RenewRequest
- type RequestMetrics
- type Server
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AuthMiddleware ¶
AuthMiddleware returns an HTTP middleware that authenticates requests using authn. The token is extracted from the Authorization header (Bearer scheme). On success, the resulting auth.Identity is attached to the request context (retrievable via IdentityFromContext). On any failure the middleware short-circuits with a 401 JSON envelope.
Pass a non-nil Authenticator to produce a working middleware. To disable authentication entirely (dev mode), pass `nil` for the `authn` parameter to NewMux instead of using this middleware.
func ChainMiddleware ¶
func ChainMiddleware(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler
ChainMiddleware wraps handler with the given middleware functions in left-to-right order. The first middleware in the list is the outermost wrapper.
func IdentityFromContext ¶
IdentityFromContext returns the authenticated identity attached to ctx, or nil if the request was unauthenticated (no-auth mode).
func LoggingMiddleware ¶ added in v0.2.0
LoggingMiddleware emits one structured access-log line per request: method, path, matched route, status, latency, correlation id, and — when the caller authenticated — the holder and tenant. It never logs the bearer token. It is meant to be the outermost wrapper so it observes the final status (including auth rejections) and owns the correlation id, which it also echoes in the X-Request-Id response header. /healthz is logged at debug to keep liveness probes out of the steady-state log.
func MetricsMiddleware ¶ added in v0.2.0
func MetricsMiddleware(m RequestMetrics) func(http.Handler) http.Handler
MetricsMiddleware records RED metrics for every request passing through it. It should wrap the mux outside auth/handlers so the recorded status reflects the final response, including auth rejections. The route label is taken from http.Request.Pattern, which the mux populates during routing, so it is read after the inner handler returns.
func NewMux ¶
func NewMux(mgr LeaseManager, authn auth.Authenticator, authz tenant.Authorizer) *http.ServeMux
NewMux returns the HTTP routes for the API server.
- /healthz is an always-200 liveness route, served unauthenticated.
- /readyz is an unauthenticated readiness route: when mgr implements ReadinessChecker it probes the backend and answers 503 on error so the pod is drained during a store outage; otherwise it answers 200.
- The /v1alpha1/* lease endpoints are served only when mgr is non-nil.
- When authn is non-nil, every lease endpoint is wrapped in AuthMiddleware and authorized by authz against the request namespace and holder; authz defaults to tenant.NewDefaultAuthorizer when nil. When authn is nil, the lease endpoints are unauthenticated and unauthorized — intended only for `--auth-mode=none` development setups; cmd/apiserver logs a loud warning in that case.
func RequestIDFromContext ¶ added in v0.2.0
RequestIDFromContext returns the correlation id assigned to the request, or "" if no observability middleware is installed. Handlers use it to correlate a client-facing response with the server-side log line.
Types ¶
type AcquireRequest ¶
AcquireRequest is the JSON body of POST .../acquire.
type LeaseManager ¶
type LeaseManager interface {
Acquire(ctx context.Context, key lease.Key, holder string, ttl time.Duration) (lease.AcquireResult, error)
Renew(ctx context.Context, key lease.Key, holder string, token int32, ttl time.Duration) (lease.AcquireResult, error)
Release(ctx context.Context, key lease.Key, holder string, token int32) error
}
LeaseManager is the subset of lease.Manager consumed by the HTTP layer. Defined as an interface for testability and to keep the api package free of a hard dependency on the lease package's internals.
type LeaseResponse ¶
type LeaseResponse struct {
Acquired bool `json:"acquired"`
Holder string `json:"holder,omitempty"`
FencingToken int32 `json:"fencingToken,omitempty"`
ExpiresAt time.Time `json:"expiresAt,omitempty"`
AcquiredAt time.Time `json:"acquiredAt,omitempty"`
}
LeaseResponse is the JSON body returned by acquire and renew. It mirrors lease.AcquireResult. When Acquired is false, the Holder/FencingToken/ ExpiresAt fields describe the entity currently holding the lease.
type Option ¶
type Option func(*serverConfig)
Option configures a Server.
func WithAddress ¶
WithAddress sets the server listen address.
func WithHandler ¶
WithHandler sets the server HTTP handler.
func WithTLSFiles ¶
WithTLSFiles sets the server TLS certificate and key file paths.
func WithTimeouts ¶ added in v0.2.0
WithTimeouts overrides the default HTTP server request timeouts. A non-positive value for any argument leaves the corresponding default in place, so callers can tune a single bound without restating the rest.
type ReadinessChecker ¶ added in v0.2.0
ReadinessChecker reports whether the server's backend is reachable. The lease lease.Manager satisfies it by probing its store; NewMux serves /readyz from it so a store outage drains the pod (503) instead of leaving it routable and surfacing failures as 500s.
type ReleaseRequest ¶
type ReleaseRequest struct {
Holder string `json:"holder"`
FencingToken int32 `json:"fencingToken"`
}
ReleaseRequest is the JSON body of POST .../release.
type RenewRequest ¶
type RenewRequest struct {
Holder string `json:"holder"`
FencingToken int32 `json:"fencingToken"`
TTLSeconds int32 `json:"ttlSeconds"`
}
RenewRequest is the JSON body of POST .../renew.
type RequestMetrics ¶ added in v0.2.0
type RequestMetrics interface {
// ObserveRequest records one served request. route is the matched mux
// pattern (templated, so cardinality is bounded), not the raw path.
ObserveRequest(route, method string, status int, dur time.Duration)
// ObserveOutcome records one lease request's semantic outcome (acquired,
// held-by-other, conflict, unauthorized, …) — the signal HTTP status hides.
ObserveOutcome(outcome string)
IncInflight()
DecInflight()
}
RequestMetrics is the subset of metrics recording the HTTP layer needs. Defined here as an interface so the api package stays free of a direct Prometheus dependency; internal/metrics provides the implementation.