Help us shape the future of Go! Take the 2026 Go Developer Survey

httpfixture

package
v1.140.0 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

HTTP fixture replay

NewHandler() creates an empty handler for stateless request/response exchanges. SetReusableFixtures(calls) replaces the test-wide reusable fallbacks; nil clears them. Invalid replacements leave the old fixtures intact. Replacing reusable fixtures does not reset the current step or its failures. StartStep installs a step's consumable fixtures and returns any failures from the previous step. Verify checks the current step for unexpected calls and unused fixtures.

Matching includes the method, escaped path, query parameters, JSON body, and listed request headers. JSON object key order and whitespace are ignored; array order and values matter. An absent body differs from JSON null.

Volatile request values

Use explicit request.matchers annotations rather than wildcard strings:

request:
  method: POST
  path: /requests
  headers:
    X-Request-ID: captured-header-id
  query:
    request_id: [captured-query-id]
  body:
    json:
      request_id: captured-body-id
      name: fixed-name
  matchers:
    headers:
      X-Request-ID: any_string
    query:
      request_id: any_string
    json:
      - path: [request_id]
        type: any_string
response:
  status: 200

any_string requires a present string, including an empty string; it does not match a missing value, JSON null, or another JSON type. Header names are case-insensitive. Header/query matchers require exactly one value and override the corresponding sample if supplied; the sample may also be omitted. Unlisted headers remain ignored. Unmatched query keys/values remain exact, including multiplicity and value order; extra query keys fail.

JSON paths use literal string keys and zero-based integer array indices, for example [items, 0, request_id]. An explicit path: [] selects a scalar JSON body. The target must exist as a string or null sample in body.json; null is only a placeholder and does not make null match. Other fields, object keys, array lengths/order, and numeric values remain exact. Invalid matcher types, duplicate targets, and paths absent from the sample fail when fixtures are loaded.

In Go, use Request.Matchers with AnyString and JSONMatcher paths. Matchers do not modify the original samples, so a future recorder can keep captured values alongside these annotations. Response payloads remain literal; there are no captures, substitutions, regexes, or magic payload strings/objects. "any_string" and "****" without annotations still match only those strings.

Consumption and ordering

Independent request signatures may interleave. Identical signatures consume responses FIFO. Requests and fixture consumption are protected by a mutex. If matcher signatures overlap, the first matching unconsumed fixture wins; there is no preference for a more specific fixture. Different captured samples overridden by the same matchers therefore consume responses FIFO too. SetEnforceCallOrder(true) optionally requires all consumable calls in their listed order within each step. Out-of-order requests fail without consuming their fixture. The setting survives step transitions; changing it does not clear consumption or failures. Reusable fallbacks remain outside ordering, but cannot bypass an out-of-order matching consumable call. Test-wide reusable exchanges are intended for invariant client initialization, such as host metadata; they are not required to be consumed.

Documentation

Overview

Package httpfixture replays HTTP exchanges without simulating remote state.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Body

type Body struct {
	JSON any `yaml:"json"`
}

Body distinguishes an absent HTTP body from a JSON value, including JSON null.

type Call

type Call struct {
	Request  Request  `yaml:"request"`
	Response Response `yaml:"response"`
}

Call pairs a request signature with its response.

type Handler

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

Handler permits independent requests to interleave and consumes identical request signatures FIFO. A mutex keeps matching and consumption atomic.

func NewHandler

func NewHandler() *Handler

NewHandler returns an empty handler; fixture sets are configured separately.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP prefers consumable step fixtures over reusable fallbacks. Matching and consumption share a lock so concurrent requests cannot consume a call twice.

func (*Handler) SetEnforceCallOrder

func (h *Handler) SetEnforceCallOrder(enabled bool)

SetEnforceCallOrder requires consumable calls in fixture order when enabled. Reusable fallbacks remain unordered. Changing this setting preserves the current step's consumption and failures.

func (*Handler) SetReusableFixtures

func (h *Handler) SetReusableFixtures(calls []Call) error

SetReusableFixtures replaces test-wide fallback exchanges, such as metadata. They survive step transitions, may be matched repeatedly, and need not be consumed. Invalid fixtures leave the previous set intact.

func (*Handler) StartStep

func (h *Handler) StartStep(label string, calls []Call) error

StartStep reports the previous step's failures and installs the next exchanges. Installing them even after failure allows the runner to attempt cleanup.

func (*Handler) Verify

func (h *Handler) Verify() error

Verify reports unexpected requests and unconsumed step exchanges without clearing failures. Reusable fixtures are excluded from consumption checks.

type JSONMatcher

type JSONMatcher struct {
	Path []any   `yaml:"path"`
	Type Matcher `yaml:"type"`
}

JSONMatcher selects a literal object key or zero-based array index at each path segment. An explicit empty path selects the whole JSON body.

type Matcher

type Matcher string

Matcher relaxes a selected request value without changing literal payloads.

const AnyString Matcher = "any_string"

AnyString requires a present string, including the empty string. It does not capture values or substitute them into later requests or responses.

type Matchers

type Matchers struct {
	Headers map[string]Matcher `yaml:"headers,omitempty"`
	Query   map[string]Matcher `yaml:"query,omitempty"`
	JSON    []JSONMatcher      `yaml:"json,omitempty"`
}

Matchers override only the selected request values. Headers and query keys require exactly one value; JSON targets must exist in the sample body. Keeping these annotations outside the payload avoids reserved JSON keys.

type Request

type Request struct {
	Method   string              `yaml:"method"`
	Path     string              `yaml:"path"`
	Query    map[string][]string `yaml:"query,omitempty"`
	Headers  map[string]string   `yaml:"headers,omitempty"`
	Body     *Body               `yaml:"body"`
	Matchers Matchers            `yaml:"matchers,omitempty"`
}

Request defines a complete signature; only listed headers are compared.

type Response

type Response struct {
	Status  int               `yaml:"status"`
	Headers map[string]string `yaml:"headers,omitempty"`
	Body    *Body             `yaml:"body"`
}

Response defines the HTTP reply, with an optional JSON body.

Jump to

Keyboard shortcuts

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