Documentation
¶
Overview ¶
Package httpx provides a Gin-based HTTP server with built-in middleware, a health/readiness/metrics surface, typed request helpers, a JSON client with retries and a circuit breaker, and web/callback helpers.
Index ¶
- Constants
- func Body[T any](c *gin.Context) (T, error)
- func GetBoolQuery(c *gin.Context, key string) (bool, error)
- func GetInt32Param(c *gin.Context, key string) (int32, error)
- func GetInt32Query(c *gin.Context, key string) (int32, error)
- func GetInt64Param(c *gin.Context, key string) (int64, error)
- func GetInt64Query(c *gin.Context, key string) (int64, error)
- func GetParam(c *gin.Context, key string) (string, error)
- func GetQuery(c *gin.Context, key string) (*string, error)
- func GetTenantID(c *gin.Context) (uuid.UUID, error)
- func GetTenantUserID(c *gin.Context) (uuid.UUID, uuid.UUID, error)
- func GetUUIDParam(c *gin.Context, key string) (uuid.UUID, error)
- func GetUUIDQuery(c *gin.Context, key string) (uuid.UUID, error)
- func GetUserID(c *gin.Context) (uuid.UUID, error)
- func LoggerFrom(ctx context.Context) *slog.Logger
- func MergeParams(r *http.Request) map[string]string
- func Module(name ...string) host.Module
- func PagedRequest(c *gin.Context) *types.PagedResultRequest
- func RequestID(c *gin.Context) string
- func UseJSONFieldNames()
- func ValidationError(err error) *errorx.Error
- func WriteAutoPostForm(w http.ResponseWriter, action string, fields map[string]string) error
- type Client
- func (c *Client) Do(ctx context.Context, method, path string, body, out any, opts ...RequestOption) error
- func (c *Client) GetJSON(ctx context.Context, path string, out any, opts ...RequestOption) error
- func (c *Client) PostJSON(ctx context.Context, path string, body, out any, opts ...RequestOption) error
- type ClientOption
- func WithCircuitBreaker(threshold int, cooldown time.Duration) ClientOption
- func WithDefaultHeader(key, value string) ClientOption
- func WithHTTPClient(h *http.Client) ClientOption
- func WithRetry(maxRetries int, baseBackoff time.Duration) ClientOption
- func WithRetryableMethods(methods ...string) ClientOption
- func WithRetryableStatuses(statuses ...int) ClientOption
- func WithTimeout(d time.Duration) ClientOption
- type QueryParamBase
- type ReadinessFunc
- type RequestOption
- type Server
- func (s *Server) AddReadinessCheck(name string, fn ReadinessFunc)
- func (s *Server) Addr() string
- func (s *Server) Close() error
- func (s *Server) CloseOrder() int
- func (s *Server) ErrCh() <-chan error
- func (s *Server) Init() error
- func (s *Server) ReadConfig(l configx.Reader) error
- func (s *Server) SetConfigSection(section string)
- func (s *Server) Start() error
- func (s *Server) Stop(ctx context.Context) error
- type ServerConfig
Constants ¶
const DefaultBreakerCooldown = 30 * time.Second
DefaultBreakerCooldown is how long the breaker stays open before allowing a trial request.
const DefaultBreakerThreshold = 5
DefaultBreakerThreshold is the number of consecutive server-side failures that trips the breaker open.
const DefaultClientTimeout = 30 * time.Second
DefaultClientTimeout bounds every request made by a Client that was not given its own *http.Client, so a hung upstream cannot block a caller forever.
const DefaultMaxBackoff = 30 * time.Second
DefaultMaxBackoff caps the per-attempt retry wait.
Variables ¶
This section is empty.
Functions ¶
func Body ¶
Body decodes and validates the JSON request body into a value of type T. It returns the value directly (not a pointer): request bodies are value-shaped data, and returning T avoids a nil-pointer footgun on the error path. A binding or `validate`/`binding` tag failure is returned as a structured BadRequest *errorx.Error with per-field details (see ValidationError), so the error middleware renders a 400 listing exactly which fields were rejected.
func GetTenantUserID ¶ added in v0.11.0
func GetUUIDParam ¶ added in v0.11.0
func GetUUIDQuery ¶ added in v0.11.0
func LoggerFrom ¶
LoggerFrom returns the request-scoped logger carried by ctx (tagged with the request id), falling back to slog.Default() when none is present.
func MergeParams ¶
MergeParams collects request parameters from both the URL query string and the POST form body into a single map, so a handler can read them uniformly whether the caller used GET or POST. When a key appears in both, the POST form value wins. It is handy for callbacks where the sender's method is not under your control (e.g. payment-gateway return URLs).
func Module ¶ added in v0.19.0
Module installs an HTTP server into the App and manages its lifecycle: the host starts the listener during the start phase and shuts it down on close. Register routes from a feature module's Setup hook (or app.Setup), which runs after services are initialized but before the server begins serving:
host.MustNew().
WithModule(httpx.Module()).
Setup(func(a *host.App) error {
httpx.Of(a).Router.GET("/healthz", handler)
return nil
}).
MustRun()
The server registers a /readyz probe that, at request time, asks every registered service implementing core.HealthChecker whether it is ready, so services added before or after this module are all covered.
Pass an optional name to install several servers side by side; a named server reads its own [http.<name>] config section (so it can bind a different port) and is retrieved with httpx.Of(app, name).
func PagedRequest ¶
func PagedRequest(c *gin.Context) *types.PagedResultRequest
PagedRequest builds a pagination request from the query string. The pageSize query param defaults to 10 when absent, and a malformed pageSize also falls back to 10 rather than erroring — listing endpoints favor a sensible default over rejecting the request.
A "page" query param (1-based) selects offset pagination for page-number jumps; when absent the request uses cursor pagination via "nextPageToken". A malformed page is ignored, falling back to cursor mode.
func RequestID ¶
RequestID returns the correlation id for the current request (set by the RequestID middleware), or "" if none.
func UseJSONFieldNames ¶ added in v0.15.0
func UseJSONFieldNames()
UseJSONFieldNames makes gin's binding validator report the json tag name (e.g. "emailAddress") rather than the Go struct field name in validation errors, so the per-field details returned by ValidationError match the keys in the request body. It is applied automatically by Body; call it directly only if you bind through gin yourself. Safe to call repeatedly and concurrently.
func ValidationError ¶ added in v0.15.0
ValidationError converts a gin binding/validation error into a structured BadRequest *errorx.Error. A validator failure carries a per-field breakdown (field name → reason) under the "fields" param; a JSON type mismatch names the offending field; anything else falls back to the raw decode message. The returned error matches errors.Is(err, errorx.ErrBadRequest).
func WriteAutoPostForm ¶
WriteAutoPostForm writes a self-submitting HTML form that POSTs fields to action and submits itself on load (with a no-script fallback button). Use it to bounce a browser to an upstream that requires a POST with hidden fields — for example a payment page that expects form-posted credentials. The action and all field names/values are HTML-escaped.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a small JSON-over-HTTP client for calling external services (payment gateways, partner APIs, internal microservices). It marshals request bodies to JSON, decodes JSON responses into a caller-supplied value, and turns non-2xx responses into structured *errorx.Error values. Construct one per upstream with NewClient and reuse it; it is safe for concurrent use.
func NewClient ¶
func NewClient(baseURL string, opts ...ClientOption) *Client
NewClient creates a Client. baseURL may be empty, in which case request paths must be absolute URLs.
func (*Client) Do ¶
func (c *Client) Do(ctx context.Context, method, path string, body, out any, opts ...RequestOption) error
Do performs a request with an optional JSON body and decodes a JSON response. It returns a *errorx.Error (Internal) for transport failures and non-2xx responses; the response body is attached to the error's Params for diagnosis. When retries are enabled (WithRetry) it transparently re-attempts retryable failures, returning the last error if all attempts fail.
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures a Client at construction time.
func WithCircuitBreaker ¶ added in v0.15.0
func WithCircuitBreaker(threshold int, cooldown time.Duration) ClientOption
WithCircuitBreaker enables a per-client circuit breaker: after threshold consecutive server-side failures (transport errors and 5xx; a 4xx does not count) requests fail fast with a "circuit breaker open" error for cooldown, after which one trial request probes recovery. Pass 0 for either argument to use the defaults (DefaultBreakerThreshold, DefaultBreakerCooldown). It pairs well with WithRetry: retries smooth over blips, the breaker sheds load when an upstream is genuinely down.
func WithDefaultHeader ¶
func WithDefaultHeader(key, value string) ClientOption
WithDefaultHeader adds a header sent on every request (e.g. an API key).
func WithHTTPClient ¶
func WithHTTPClient(h *http.Client) ClientOption
WithHTTPClient sets the underlying *http.Client (for custom timeouts, proxies, or transport-level instrumentation).
func WithRetry ¶
func WithRetry(maxRetries int, baseBackoff time.Duration) ClientOption
WithRetry enables automatic retries: up to maxRetries extra attempts on transport errors and retryable status codes, using exponential backoff with jitter starting at baseBackoff. Only idempotent methods are retried by default (GET, HEAD, PUT, DELETE, OPTIONS); customize with WithRetryableMethods and WithRetryableStatuses. Retries always honor the request context.
func WithRetryableMethods ¶
func WithRetryableMethods(methods ...string) ClientOption
WithRetryableMethods overrides which HTTP methods are eligible for retry.
func WithRetryableStatuses ¶
func WithRetryableStatuses(statuses ...int) ClientOption
WithRetryableStatuses overrides which response status codes trigger a retry.
func WithTimeout ¶
func WithTimeout(d time.Duration) ClientOption
WithTimeout sets the request timeout on the default client. Ignored if WithHTTPClient supplied a client.
type QueryParamBase ¶
type QueryParamBase struct {
// contains filtered or unexported fields
}
func (*QueryParamBase) BindQueryParams ¶
func (q *QueryParamBase) BindQueryParams(c *gin.Context, target any) error
BindQueryParams maps query parameters onto the tagged fields of target (a pointer to a struct) and records them in the param map. A malformed value (e.g. ?id=notauuid) returns a core.BadRequest error naming the offending parameter rather than silently substituting a zero value.
func (*QueryParamBase) GetMap ¶
func (q *QueryParamBase) GetMap() map[string]any
func (*QueryParamBase) SetField ¶
func (q *QueryParamBase) SetField(name string, value any)
type ReadinessFunc ¶
ReadinessFunc reports whether a dependency is ready to serve traffic. It should return nil when healthy and an error describing the problem otherwise.
type RequestOption ¶
RequestOption customises a single request (e.g. a per-call bearer token).
func WithHeader ¶
func WithHeader(key, value string) RequestOption
WithHeader sets a header on one request, overriding any default of the same key.
type Server ¶
func NewServer ¶
func NewServer(cfg ServerConfig, logger *slog.Logger) *Server
NewServer creates the router with its middleware stack and standard routes (/health, /metrics, /readyz, and /swagger if debug). The server does not start listening until Init is called.
func Of ¶ added in v0.19.0
Of returns the HTTP server installed by Module under the optional name, panicking if none was installed. Use it from Setup hooks and handlers to reach the router, e.g. httpx.Of(app).Router or httpx.Of(app, "admin").Router.
func (*Server) AddReadinessCheck ¶
func (s *Server) AddReadinessCheck(name string, fn ReadinessFunc)
AddReadinessCheck registers a named dependency probe consulted by GET /readyz. Safe for concurrent use.
func (*Server) Addr ¶
Addr returns the listener address. Before Init it is derived from the config; after Init it reflects the bound address.
func (*Server) Close ¶ added in v0.4.0
Close implements core.Closer, gracefully draining and stopping the server.
func (*Server) CloseOrder ¶ added in v0.19.0
CloseOrder closes the HTTP server early (as an edge), so it stops accepting connections and drains in-flight requests before the backends those handlers use (database, cache, broker) are torn down.
func (*Server) ErrCh ¶ added in v0.4.0
ErrCh returns the channel that receives the server's exit error (or nil on clean shutdown via Stop). The host reads this to react to unexpected failures.
func (*Server) Init ¶ added in v0.4.0
Init implements core.Initer. It builds the underlying http.Server but does not begin listening, leaving a window for setup work (route registration) before the server serves. Call Start (the host does this in its start phase) to serve.
func (*Server) ReadConfig ¶ added in v0.11.0
ReadConfig implements configx.Configurable, reading the server's config section (default "http") so the server owns its configuration independently of host.Config.
func (*Server) SetConfigSection ¶ added in v0.19.0
SetConfigSection overrides the config section the server reads (default "http"). Named servers use it to read their own [http.<name>] section so several servers can bind different ports.
type ServerConfig ¶
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package middleware provides Gin middleware for MicroJet's HTTP server: request IDs, structured logging, error translation, metrics, CORS, rate limiting, JWT auth, idempotency, tracing, and multi-tenant resolution.
|
Package middleware provides Gin middleware for MicroJet's HTTP server: request IDs, structured logging, error translation, metrics, CORS, rate limiting, JWT auth, idempotency, tracing, and multi-tenant resolution. |