Skip to content

struct0x/hx

Repository files navigation

hx

import "github.com/struct0x/hx"

Index

func Bind

func Bind[T any](r *http.Request, dst *T, opts ...BindOpt) error

Bind extracts data from an HTTP request into a destination struct. It supports binding from multiple sources including URL query parameters, path variables, headers, cookies, JSON body, and multipart file uploads.

The destination must be a pointer to a struct. Fields in the struct are bound based on struct tags that specify the data source and field name:

  • `query:"name"` - binds from URL query parameters
  • `path:"name"` - binds from URL path variables
  • `header:"Name"` - binds from HTTP headers
  • `cookie:"name"` - binds from HTTP cookies
  • `json:"name"` - binds from JSON request body (application/json)
  • `file:"name"` - binds file uploads from multipart/form-data

Supported field types include:

  • Basic types: string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64
  • Slices of basic types (for multiple values)
  • Slices of strings (for headers and query parameters with multiple values)
  • http.Cookie (for cookie fields)
  • multipart.FileHeader (for single file uploads)
  • []*multipart.FileHeader (for multiple file uploads)
  • Types implementing encoding.TextUnmarshaler
  • Any type for json-tagged fields (unmarshaled via encoding/json)

Options:

  • WithPathValueFunc: provides a custom function to extract path variables from the request. By default, uses http.Request.PathValue.
  • WithMaxFormMemoryMB: sets the maximum memory in megabytes for parsing multipart forms. Defaults to 32 MB if not specified.
  • WithValidator: sets a custom validator.Validate instance to be used for request validation. By default, a default validator is used.

Returns:

  • nil if all fields are successfully bound
  • error if any field fails to bind, use BindProblem to create a structured error response

Example usage:

type UserRequest struct {
    ID       int      `path:"id"`
    Name     string   `json:"name"`
    Email    string   `json:"email"`
    Tags     []string `query:"tags"`
    AuthToken string  `header:"Authorization"`
}

func handler(ctx context.Context, r *http.Request) error {
    var req UserRequest
    if err := hx.Bind(r, &req); err != nil {
        return BindProblem(err, "Invalid user request",
        	WithTypeURI("https://example.com/errors/invalid-user"))
    }
    // Use req...
    return nil
}

func BindProblem(err error, summary string, opts ...ProblemOpt) error

BindProblem creates a structured error response by wrapping binding errors into a ProblemDetails. It takes an error from Bind, a summary message, and optional ProblemOpt options.

The function handles different types of binding errors:

  • Structural errors (nil request, nil destination, invalid types) return 500 Internal Server Error
  • Validation errors return 400 Bad Request with detailed field errors in the extensions
  • Other errors return 500 Internal Server Error

For validation errors, the response includes an "errors" field in the extensions containing an array of objects with "field" and "detail" properties for each validation error.

Allowed ProblemOpt options: - WithTypeURI sets the Type field of ProblemDetails. - WithDetail sets the Detail field of ProblemDetails. - WithField adds a single field to the Extensions map of ProblemDetails. - WithFields sets multiple fields at once. - WithInstance sets the Instance field of ProblemDetails. Note: WithCause option is automatically added and will be ignored if provided manually.

Example usage:

var req UserRequest
if err := Bind(r, &req); err != nil {
    return BindProblem(err, "Invalid user request",
        WithTypeURI("https://example.com/errors/invalid-user"))
}

func HijackResponseWriter(ctx context.Context) http.ResponseWriter

HijackResponseWriter retrieves the http.ResponseWriter from the context. When the ResponseWriter is hijacked, the return value from HandlerFunc will be ignored.

type BindOpt

type BindOpt = bind.Opt

func WithMaxFormMemoryMB(maxFormMemoryMB int64) BindOpt

WithMaxFormMemoryMB configures the maximum size of multipart form data that will reside in memory. The rest of the data will be stored on disk in temporary files. This option is used when binding multipart form data and file uploads.

func WithPathValueFunc(fn func(r *http.Request, name string) string) BindOpt

WithPathValueFunc overrides the default way of extracting a path parameter from the request. The function receives the request and the name of the path variable and must return the value (or the empty string if the variable is not present).

func WithValidator(v *validator.Validate) BindOpt

WithValidator configures a custom validator.Validate instance to be used for request validation. The validator will be used to validate struct fields with "validate" tags after binding. If not provided, a default validator will be used.

type Documented interface {
    Doc() RouteDoc
}

type Field

Field represents a key-value pair that can be added to ProblemDetails extensions.

type Field struct {
    Key string
    Val any
}

func F

func F(k string, v any) Field

F is a shorthand constructor for creating Field instances.

type HX

HX is a framework for building HTTP APIs with enhanced error handling and middleware support. It provides a convenient way to handle HTTP requests, manage middleware chains, and standardize error responses using ProblemDetails (RFC 9457).

Example usage:

hx := hx.New(
    hx.WithLogger(slog.Default()),
    hx.WithCustomMux(http.NewServeMux()),
    hx.WithMiddleware(loggingMiddleware),
)

// HandleFunc requests
hx.HandleFunc("/api/users", func(ctx context.Context, r *http.Request) error {
    // HandleFunc the request
    return nil
})

// Start the server
http.ListenAndServe(":8080", hx)
type HX struct {
    // contains filtered or unexported fields
}

func New

func New(opts ...Opt) *HX

New creates a new HX instance.

func (*HX) Group

func (h *HX) Group(prefix string, mids ...Middleware) *HX

Group creates a sub-router sharing the same mux, with the given path prefix and additional middlewares appended to the current chain.

Example:

api := server.Group("/api/v1", authMiddleware)
api.HandleFunc("POST /users", createUserHandler)   // registers "POST /api/v1/users"
api.HandleFunc("/orders", listOrdersHandler)        // registers "/api/v1/orders"

admin := api.Group("/admin", adminOnlyMiddleware)
admin.HandleFunc("/stats", statsHandler)            // registers "/api/v1/admin/stats"

func (*HX) Handle

func (h *HX) Handle(pattern string, handler Handler, mids ...Middleware)

func (*HX) HandleFunc

func (h *HX) HandleFunc(pattern string, handler HandlerFunc, opts ...RouteOpt)

HandleFunc registers a new request handler with the given pattern and route options. Options can be Middleware values or a Doc describing the route for spec generation.

func (*HX) Routes

func (h *HX) Routes() []RouteInfo

Routes returns all routes registered on this server, including those registered via groups.

func (*HX) ServeHTTP

func (h *HX) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Handler

type Handler interface {
    ServeHX(ctx context.Context, r *http.Request) error
}

HandlerFunc is a function type that handles HTTP requests in HX framework. It receives a context.Context and *http.Request as input parameters and returns an error. Context is identical to http.Request.Context, but it includes a ResponseWriter that can be hijacked.

If HandlerFunc returns: - nil: panics in dev mode, 500 in production — use hx.NoContent() for 204 responses - ProblemDetails: the response will be encoded as application/problem+json - Response: the response will be encoded as application/json with custom headers - any other error: the response will be 500 Internal Server Error

Example usage:

hx.HandlerFunc(func(ctx context.Context, r *http.Request) error {
    // HandleFunc the request
    return nil // or return an error
})
type HandlerFunc func(ctx context.Context, r *http.Request) error

Middleware wraps a HandlerFunc to form a processing chain. Return the next handler's error to propagate it or return a new error to short-circuit.

Example:

func authMiddleware(next hx.HandlerFunc) hx.HandlerFunc {
    return func(ctx context.Context, r *http.Request) error {
        if r.Header.Get("Authorization") == "" {
            return hx.Unauthorized("missing authorization header")
        }
        return next(ctx, r)
    }
}
type Middleware func(HandlerFunc) HandlerFunc

func AdaptMiddleware(m func(http.Handler) http.Handler) Middleware

AdaptMiddleware converts standard net/http middleware into a hx Middleware.

It works correctly for middleware that:

  • Enriches the request (adds context values, sets headers)
  • Short-circuits by writing a response directly (e.g. rate limiters)

It does not work for middleware that transforms the ResponseWriter itself (e.g. gzip compression). Apply those at the server level instead.

type Mux

Mux is an interface that wraps the http.Handler.

type Mux interface {
    http.Handler

    Handle(pattern string, handler http.Handler)
}

type Opt

type Opt interface {
    // contains filtered or unexported methods
}

func WithCustomMux(mux Mux) Opt

WithCustomMux sets a custom multiplexer for the HX instance. The provided mux will be used for routing HTTP requests. If not set, http.DefaultServeMux will be used.

func WithLogger(log *slog.Logger) Opt

WithLogger sets a custom logger for the HX instance. The provided logger will be used for error logging and debugging purposes. If not set, slog.Default() will be used.

func WithMiddlewares(m ...Middleware) Opt

WithMiddlewares sets middleware functions for the HX instance. These middlewares will be applied to all handlers in the order they are provided. Each middleware should implement the Middleware interface.

func WithProblemInstanceGetter(f func(ctx context.Context) string) Opt

WithProblemInstanceGetter sets a function that provides the "instance" value for ProblemDetails. This is particularly useful in distributed tracing scenarios or when using error tracking systems like Sentry, as it allows linking specific error instances to their corresponding traces or external error reports. The provided function receives a context and should return a string identifier that uniquely represents this error occurrence.

func WithProductionMode(enabled bool) Opt

WithProductionMode enables or disables production mode.

ProblemDetails is a JSON object that describes an error. https://datatracker.ietf.org/doc/html/rfc9457

type ProblemDetails = out.ProblemDetails

func BadRequest(title string, opts ...ProblemOpt) ProblemDetails

BadRequest creates an HTTP response with a 400 (Bad Request) status code. It accepts a body of any type and optional response modifiers.

func Conflict(title string, opts ...ProblemOpt) ProblemDetails

Conflict creates an HTTP response with a 409 (Conflict) status code. It accepts a body of any type and optional response modifiers.

func Forbidden(title string, opts ...ProblemOpt) ProblemDetails

Forbidden creates an HTTP response with a 403 (Forbidden) status code. It accepts a body of any type and optional response modifiers.

func Internal(title string, opts ...ProblemOpt) ProblemDetails

Internal creates an HTTP response with a 500 (Internal Server Error) status code.

func MethodNotAllowed(title string, opts ...ProblemOpt) ProblemDetails

MethodNotAllowed creates an HTTP response with a 405 (Method Not Allowed) status code. It accepts a body of any type and optional response modifiers.

func NotFound(title string, opts ...ProblemOpt) ProblemDetails

NotFound creates an HTTP response with a 404 (Not Found) status code. It accepts a body of any type and optional response modifiers.

func Problem

func Problem(status int, summary string, opts ...ProblemOpt) ProblemDetails

Problem creates a ProblemDetails instance with the provided status and summary.

func Unauthorized(title string, opts ...ProblemOpt) ProblemDetails

Unauthorized creates an HTTP response with a 401 (Unauthorized) status code. It accepts a body of any type and optional response modifiers.

type ProblemOpt interface {
    // contains filtered or unexported methods
}

Response representing an HTTP response with status, body, and headers.

type Response = out.Response

func Created

func Created(body any, opts ...ResponseOpt) Response

Created creates an HTTP response with a 201 (Created) status code. It accepts a body of any type and optional response modifiers.

func NoContent() Response

NoContent creates an HTTP response with a 204 (No Content) status code.

func OK

func OK(body any, opts ...ResponseOpt) Response

OK creates a successful HTTP response with a 200 (OK) status code. It accepts a body of any type and optional response modifiers.

func Respond

func Respond(status int, body any, opts ...ResponseOpt) Response

Respond creates an HTTP response with the specified status code and body. It accepts a status code, a body of any type, and optional response modifiers.

ResponseOpt is an interface for options that can modify both Response and ProblemDetails objects. It provides methods to apply modifications to these types, allowing for flexible configuration of HTTP responses. Implementations of this interface can modify headers, cookies, and other response attributes consistently across both normal responses and problem details.

type ResponseOpt interface {
    // contains filtered or unexported methods
}

RouteDoc describes an HTTP operation for API documentation and spec generation.

type RouteDoc struct {
    // Request is a zero-value of the request struct.
    // Struct tags drive parameter and body extraction:
    //   json:     request body field
    //   path:     path parameter
    //   query:    query parameter
    //   header:   header parameter
    //   cookie:   cookie parameter
    //   validate: constraints (required, min, max, enum, ...)
    Request any

    // Response is a zero-value of the primary success response body (200 OK).
    Response any

    // Responses document additional status codes and their response body types.
    // Takes precedence over Response for the same status code.
    // Use nil as the value to document a no-body response (e.g. 204).
    //   map[int]any{
    //       http.StatusCreated:   OrderResponse{},
    //       http.StatusNoContent: nil,
    //   }
    Responses map[int]any

    // Errors list extra HTTP status codes this route returns as ProblemDetails.
    // 400 and 500 are implicitly included on all routes.
    // Only declare route-specific ones: 404, 409, 422, etc.
    Errors []int

    // Tags group this operation in the generated spec (e.g. "orders", "users").
    Tags []string

    // Summary is a short one-line description shown in tooling.
    Summary string

    // Description is a longer explanation. Markdown supported.
    Description string

    // OperationID is a unique identifier for code generators.
    // Auto-derived from method + path if empty (e.g. "post_orders").
    OperationID string

    // Security references security scheme names defined at the server level.
    // e.g. []string{"BearerAuth"}
    Security []string

    // Deprecated marks this operation as deprecated in the spec.
    Deprecated bool
}

RouteInfo is a registered route with its method, path, and optional documentation.

type RouteInfo struct {
    Method string
    Path   string
    Doc    *RouteDoc
}

RouteOpt is implemented by Middleware and Doc. Pass one or more RouteOpts to HandleFunc to configure a route.

type RouteOpt interface {
    // contains filtered or unexported methods
}

func Doc

func Doc(d RouteDoc) RouteOpt

Doc wraps a RouteDoc to be passed to HandleFunc alongside middlewares.

server.HandleFunc("POST /orders", HandleCreateOrder(svc),
    hx.Doc(hx.RouteDoc{
        Request:  CreateOrderRequest{},
        Response: OrderResponse{},
        Summary:  "Create a new order",
        Tags:     []string{"orders"},
    }),
)

example

import "github.com/struct0x/hx/example"

Index

func HandleBanUser() hx.HandlerFunc

func HandleCancelOrder() hx.HandlerFunc

func HandleCreateOrder() hx.HandlerFunc

func HandleCreateUser() hx.HandlerFunc

func HandleGetOrder() hx.HandlerFunc

func HandleGetStats() hx.HandlerFunc

func HandleGetUser() hx.HandlerFunc

func HandleIngestEvent() hx.HandlerFunc

func HandleListOrders() hx.HandlerFunc

func HandleUpdateOrderStatus() hx.HandlerFunc

type BanUserRequest struct {
    ID     string `path:"id"      validate:"required"`
    Reason string `json:"reason"  validate:"required,min=10,max=500"`
}

type CancelOrderRequest struct {
    ID     string `path:"id"     validate:"required"`
    Reason string `json:"reason" validate:"omitempty,max=500"`
}

type CreateOrderRequest struct {
    UserID      string `header:"X-User-ID"  validate:"required"`
    ProductName string `json:"product_name" validate:"required,min=2,max=100"`
    Quantity    int    `json:"quantity"     validate:"required,gte=1,lte=1000"`
    Notes       string `json:"notes"        validate:"omitempty,max=500"`
}

type CreateOrderResponse struct {
    Order   *Order `json:"order"`
    Message string `json:"message"`
}

type CreateUserRequest struct {
    Email     string `json:"email"      validate:"required,email"`
    FirstName string `json:"first_name" validate:"required,alpha,min=2,max=50"`
    LastName  string `json:"last_name"  validate:"required,alpha,min=2,max=50"`
    Phone     string `json:"phone"      validate:"omitempty,e164"`
    Country   string `json:"country"    validate:"omitempty,iso3166_1_alpha2"`
}

type GetOrderRequest struct {
    ID string `path:"id" validate:"required"`
}

type GetUserRequest struct {
    ID      string `path:"id"      validate:"required"`
    Verbose bool   `query:"verbose"`
}

type IngestEventRequest struct {
    EventType string         `json:"event_type" validate:"required,oneof=order.created order.cancelled user.registered"`
    Payload   map[string]any `json:"payload"    validate:"required"`
}

type ListOrdersRequest struct {
    UserID  string `header:"X-User-ID" validate:"required"`
    Status  string `query:"status"     validate:"omitempty,oneof=pending processing shipped delivered cancelled"`
    SortBy  string `query:"sort_by"    validate:"omitempty,oneof=created_at total_price"`
    Page    int    `query:"page"       validate:"omitempty,gte=1"`
    PerPage int    `query:"per_page"   validate:"omitempty,gte=1,lte=100"`
}

type Order

type Order struct {
    ID          string    `json:"id"`
    UserID      string    `json:"user_id"`
    ProductName string    `json:"product_name"`
    Quantity    int       `json:"quantity"`
    TotalPrice  float64   `json:"total_price"`
    Status      string    `json:"status"`
    Notes       string    `json:"notes,omitempty"`
    CreatedAt   time.Time `json:"created_at"`
    UpdatedAt   time.Time `json:"updated_at"`
}

type OrderList struct {
    Orders  []Order `json:"orders"`
    Total   int     `json:"total"`
    Page    int     `json:"page"`
    PerPage int     `json:"per_page"`
}

type StatsResponse struct {
    TotalOrders   int     `json:"total_orders"`
    TotalRevenue  float64 `json:"total_revenue"`
    PendingOrders int     `json:"pending_orders"`
    TotalUsers    int     `json:"total_users"`
}

type UpdateOrderStatusRequest struct {
    ID     string `path:"id"      validate:"required"`
    Status string `json:"status"  validate:"required,oneof=processing shipped delivered cancelled"`
}

type User

type User struct {
    ID        string    `json:"id"`
    Email     string    `json:"email"`
    FirstName string    `json:"first_name"`
    LastName  string    `json:"last_name"`
    Phone     string    `json:"phone,omitempty"`
    Country   string    `json:"country,omitempty"`
    Banned    bool      `json:"banned"`
    CreatedAt time.Time `json:"created_at"`
}

hxdoc

import "github.com/struct0x/hx/hxdoc"

Package hxdoc generates an OpenAPI 3.1.0 specification from routes registered with hx.HX and exposes it as a hx.HandlerFunc.

Usage:

hx.HandleFunc("/openapi.json", hxdoc.Handler(server,
    hxdoc.WithTitle("Orders API"),
    hxdoc.WithVersion("1.0.0"),
    hxdoc.WithSecurityScheme("BearerAuth", hxdoc.BearerAuth()),
))

Index

func Handler

func Handler(server *hx.HX, opts ...Opt) hx.HandlerFunc

Handler returns an hx.HandlerFunc that serves the OpenAPI 3.1.0 spec as JSON. The spec is generated once at construction time from the routes registered on server. Only routes with an hx.Doc(...) option are included in the spec.

func UIHandler(specURL string) hx.HandlerFunc

UIHandler returns a hx.HandlerFunc that serves a Swagger UI HTML page loading the spec from specURL.

Register it on a hx server:

server.HandleFunc("GET /docs", hxdoc.UIHandler("/openapi.json"))

type Opt

Opt configures the generated OpenAPI document.

type Opt func(*config)

func WithDescription(desc string) Opt

WithDescription sets the API description in the info object.

func WithSecurityScheme(name string, scheme SecurityScheme) Opt

WithSecurityScheme adds a named security scheme to the components section.

func WithServer(url, description string) Opt

WithServer adds a server entry to the OpenAPI document.

func WithTitle(title string) Opt

WithTitle sets the API title in the info object.

func WithVersion(version string) Opt

WithVersion sets the API version in the info object.

type Schema

Schema is a JSON Schema definition for OpenAPI 3.1.0.

type Schema struct {
    Ref                  string             `json:"$ref,omitempty"`
    Type                 string             `json:"type,omitempty"`
    Format               string             `json:"format,omitempty"`
    Pattern              string             `json:"pattern,omitempty"`
    Properties           map[string]*Schema `json:"properties,omitempty"`
    Required             []string           `json:"required,omitempty"`
    Items                *Schema            `json:"items,omitempty"`
    AdditionalProperties *Schema            `json:"additionalProperties,omitempty"`
    Enum                 []any              `json:"enum,omitempty"`
    Minimum              *float64           `json:"minimum,omitempty"`
    Maximum              *float64           `json:"maximum,omitempty"`
    ExclusiveMinimum     *float64           `json:"exclusiveMinimum,omitempty"`
    ExclusiveMaximum     *float64           `json:"exclusiveMaximum,omitempty"`
    MinLength            *int               `json:"minLength,omitempty"`
    MaxLength            *int               `json:"maxLength,omitempty"`
    MinItems             *int               `json:"minItems,omitempty"`
    MaxItems             *int               `json:"maxItems,omitempty"`
    UniqueItems          bool               `json:"uniqueItems,omitempty"`
}

SecurityScheme defines an OpenAPI security scheme.

type SecurityScheme struct {
    Type         string `json:"type"`
    Scheme       string `json:"scheme,omitempty"`
    BearerFormat string `json:"bearerFormat,omitempty"`
    In           string `json:"in,omitempty"`
    Name         string `json:"name,omitempty"`
    Description  string `json:"description,omitempty"`
}

func APIKeyAuth(in, name string) SecurityScheme

APIKeyAuth returns an API key security scheme.

func BearerAuth() SecurityScheme

BearerAuth returns a Bearer token security scheme.

hxmid

import "github.com/struct0x/hx/hxmid"

Package hxmid provides standard middleware for hx applications.

Index

func Logger

func Logger(log *slog.Logger, extras ...AttrsFunc) hx.Middleware

Logger logs each request with its method, path, status code, and duration. Requests resulting in 5xx are logged at Error level, 4xx at Warn, everything else at Info.

Additional attributes can be injected per-request via optional AttrsFuncs:

hxmid.Logger(log, func(ctx context.Context, r *http.Request) []slog.Attr {
    return []slog.Attr{
        slog.String("trace_id", trace.SpanFromContext(ctx).SpanContext().TraceID().String()),
    }
})

func Recoverer(log *slog.Logger) hx.Middleware

Recoverer catches panics in downstream handlers, logs them with a stack trace, and returns a 500 Internal Server Error response.

func RequireJSON(opts ...hx.ProblemOpt) hx.Middleware

RequireJSON rejects requests with a body (POST, PUT, PATCH) that do not declare Content-Type: application/json, responding with 415 Unsupported Media Type. Optional ProblemOpts are forwarded to the error response, e.g. hx.WithTypeURI for docs links.

AttrsFunc extracts additional slog attributes from the request context. Use this to attach trace IDs, user IDs, or any other contextual fields to log entries.

type AttrsFunc func(ctx context.Context, r *http.Request) []slog.Attr

hxtest

import "github.com/struct0x/hx/hxtest"

Package hxtest provides a fluent API for testing hx.HandlerFunc.

Index

type Check

Check is a test check applied to a Result.

type Check func(t testing.TB, r *Result)

func Body

func Body(want any, opts ...cmp.Option) Check

func Header

func Header(key, want string) Check

func HeaderHas(key, substr string) Check

func IsProblem(problem error) Check

IsProblem asserts RFC 9457 style response (& Content-Type).

func NoBody

func NoBody() Check

func ProblemDetail(substr string) Check

func ProblemTitle(substr string) Check

func Status

func Status(code int) Check

type Result

Result is a materialized HTTP response produced by running a handler.

type Result struct {
    ContentType string
    Status      int
    Header      http.Header

    Body     any
    Hijacked bool
    Err      error

    Problem *out.ProblemDetails
}

type Tester

Tester is the harness builder. Create via Test(t, handler).

type Tester struct {
    // contains filtered or unexported fields
}

func Test

func Test(t testing.TB, h hx.HandlerFunc) *Tester

Test initializes a test harness for a single handler.

func (*Tester) DebugBody

func (tt *Tester) DebugBody(b bool) *Tester

DebugBody enables debug logging of the response body.

func (*Tester) Do

func (tt *Tester) Do(req *http.Request) *Result

Do run the handler against req, honoring HijackResponseWriter semantics, materializes the result, then runs queued expectations (fail-fast).

func (*Tester) Expect

func (tt *Tester) Expect(e Check) *Tester

Expect queues an assertion to run after the handler is executed.

func (*Tester) Expects

func (tt *Tester) Expects(ee ...Check) *Tester

Expects queues multiple assertions to run after the handler is executed.

func (*Tester) WithContext

func (tt *Tester) WithContext(mut func(ctx context.Context) context.Context) *Tester

WithContext lets you mutate the request context before invocation.

internal

import "github.com/struct0x/hx/internal"

Index

func HijackResponseWriter(ctx context.Context) http.ResponseWriter

HijackResponseWriter retrieves the http.ResponseWriter from the context and marks it as taken. When hijacked, the return value from HandlerFunc will be ignored.

func PeekResponseWriter(ctx context.Context) (http.ResponseWriter, *atomic.Bool)

PeekResponseWriter retrieves the http.ResponseWriter and its write flag from context without marking it as hijacked.

func WithResponseWriter(ctx context.Context, rwRead *atomic.Bool, rw http.ResponseWriter) context.Context

WithResponseWriter stores the http.ResponseWriter in the context. It returns a new context containing the response writer.

bind

import "github.com/struct0x/hx/internal/bind"

Index

Variables

var (
    ErrNilRequest     = errors.New("bind: request is nil")
    ErrNilDestination = errors.New("bind: destination is nil")
    ErrNotAStruct     = errors.New("bind: destination must be a struct")
    ErrExpectedStruct = errors.New("bind: expected struct")
    ErrMultipleTags   = errors.New("bind: multiple tags")
    ErrEmptyTag       = errors.New("bind: tag is empty")
)

func Bind

func Bind(r *http.Request, dst any, opts ...Opt) error

type Error

Error represents a failure to bind a single struct field.

type Error struct {
    Field string // struct field name
    Err   error  // underlying error (conversion, missing tag, etc.)
}

func (Error) Error

func (e Error) Error() string

Error implements the error interface.

type Errors

Errors aggregate one or more BindError values. It implements the error interface.

type Errors struct {
    Errors []Error
}

func (*Errors) Append

func (es *Errors) Append(err Error)

func (*Errors) Error

func (es *Errors) Error() string

Error returns a human‑readable summary.

func (*Errors) Unwrap

func (es *Errors) Unwrap() []error

Unwrap enables errors.Is / errors.As to work on individual errors.

type Opt

Opt is a functional option that configures the binder.

type Opt interface {
    BindOpt()
}

func WithMaxFormMemoryMB(maxFormMemoryMB int64) Opt

func WithPathValueFunc(fn func(r *http.Request, name string) string) Opt

func WithValidator(v *validator.Validate) Opt

out

import "github.com/struct0x/hx/internal/out"

Index

ProblemDetails is a JSON object that describes an error. https://datatracker.ietf.org/doc/html/rfc9457

type ProblemDetails struct {
    // Type is a URI reference [RFC3986] that identifies the problem type.
    Type string
    // StatusCode is the HTTP status code generated by the origin server for this occurrence of the problem.
    StatusCode int
    // Title contains a short, human-readable summary of the problem.
    Title string
    // Detail contains a human-readable explanation specific to this occurrence of the problem.
    Detail string
    // Instance is a URI reference that identifies the specific occurrence of the problem.
    Instance string

    // Extensions is a map of additional information about the problem. They will be inlined in the JSON response.
    Extensions map[string]any
    // Cause is the underlying error that caused this problem. This will be logged.
    Cause error

    Headers http.Header
    Cookies []*http.Cookie
}

func (ProblemDetails) Error

func (p ProblemDetails) Error() string

func (ProblemDetails) MarshalJSON

func (p ProblemDetails) MarshalJSON() ([]byte, error)

func (*ProblemDetails) UnmarshalJSON

func (p *ProblemDetails) UnmarshalJSON(bytes []byte) error

func (ProblemDetails) Unwrap

func (p ProblemDetails) Unwrap() error

type Response struct {
    ContentType string
    StatusCode  int
    Body        any
    Headers     http.Header
    Cookies     []*http.Cookie
}

func (Response) Error

func (r Response) Error() string

Generated by gomarkdoc

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors