httpx

package module
v0.21.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 32 Imported by: 0

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

View Source
const DefaultBreakerCooldown = 30 * time.Second

DefaultBreakerCooldown is how long the breaker stays open before allowing a trial request.

View Source
const DefaultBreakerThreshold = 5

DefaultBreakerThreshold is the number of consecutive server-side failures that trips the breaker open.

View Source
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.

View Source
const DefaultMaxBackoff = 30 * time.Second

DefaultMaxBackoff caps the per-attempt retry wait.

Variables

This section is empty.

Functions

func Body

func Body[T any](c *gin.Context) (T, error)

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 GetBoolQuery added in v0.11.0

func GetBoolQuery(c *gin.Context, key string) (bool, error)

func GetInt32Param added in v0.11.0

func GetInt32Param(c *gin.Context, key string) (int32, error)

func GetInt32Query added in v0.11.0

func GetInt32Query(c *gin.Context, key string) (int32, error)

func GetInt64Param added in v0.11.0

func GetInt64Param(c *gin.Context, key string) (int64, error)

func GetInt64Query added in v0.11.0

func GetInt64Query(c *gin.Context, key string) (int64, error)

func GetParam added in v0.11.0

func GetParam(c *gin.Context, key string) (string, error)

func GetQuery added in v0.11.0

func GetQuery(c *gin.Context, key string) (*string, error)

func GetTenantID added in v0.11.0

func GetTenantID(c *gin.Context) (uuid.UUID, error)

func GetTenantUserID added in v0.11.0

func GetTenantUserID(c *gin.Context) (uuid.UUID, uuid.UUID, error)

func GetUUIDParam added in v0.11.0

func GetUUIDParam(c *gin.Context, key string) (uuid.UUID, error)

func GetUUIDQuery added in v0.11.0

func GetUUIDQuery(c *gin.Context, key string) (uuid.UUID, error)

func GetUserID added in v0.11.0

func GetUserID(c *gin.Context) (uuid.UUID, error)

func LoggerFrom

func LoggerFrom(ctx context.Context) *slog.Logger

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

func MergeParams(r *http.Request) map[string]string

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

func Module(name ...string) host.Module

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

func RequestID(c *gin.Context) string

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

func ValidationError(err error) *errorx.Error

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

func WriteAutoPostForm(w http.ResponseWriter, action string, fields map[string]string) error

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.

func (*Client) GetJSON

func (c *Client) GetJSON(ctx context.Context, path string, out any, opts ...RequestOption) error

GetJSON issues a GET and decodes the JSON response into out (which may be nil to discard the body).

func (*Client) PostJSON

func (c *Client) PostJSON(ctx context.Context, path string, body, out any, opts ...RequestOption) error

PostJSON marshals body to JSON, issues a POST, and decodes the JSON response into out (either may be nil).

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

type ReadinessFunc func(ctx context.Context) error

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

type RequestOption func(*http.Request)

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

type Server struct {
	Router *gin.Engine
	// contains filtered or unexported fields
}

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

func Of(app *host.App, name ...string) *Server

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

func (s *Server) Addr() string

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

func (s *Server) Close() error

Close implements core.Closer, gracefully draining and stopping the server.

func (*Server) CloseOrder added in v0.19.0

func (s *Server) CloseOrder() int

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

func (s *Server) ErrCh() <-chan error

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

func (s *Server) Init() error

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

func (s *Server) ReadConfig(l configx.Reader) error

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

func (s *Server) SetConfigSection(section string)

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.

func (*Server) Start

func (s *Server) Start() error

Start implements core.Starter. It begins serving in a background goroutine; the outcome is available via ErrCh once the server stops (nil on clean shutdown, error otherwise). Init must have run first.

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

type ServerConfig

type ServerConfig struct {
	Host  string `mapstructure:"host"`
	Port  int    `mapstructure:"port"`
	Debug bool   `mapstructure:"debug"`
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL