Skip to content

httpmock: with-body-closure

Back to gallery

Exhibit path: docs/examples/codegen/httpmock/with-body-closure/

A handler that uses a body closure to generate response bodies per call. Shows how to return different payloads on repeated requests to the same route without registering multiple handlers.

Input (in.go)

go
//go:build glacier_codegen_fixture

// Package apiclient defines the HTTP transport for the dynamic API client.
package apiclient

import "net/http"

// DynamicTransport is an HTTP transport that generates response bodies per call.
//
// +glacier:mock
// +glacier:httpmock body=closure
type DynamicTransport interface {
	// RoundTrip executes an HTTP request.
	RoundTrip(req *http.Request) (*http.Response, error)
}

Output (out.go)

go
//go:build glacier_codegen_fixture

// Code generated by glaciergen. DO NOT EDIT.
// Source: in.go
package apiclient

import (
	"io"
	"net/http"

	"github.com/nathanbrophy/glacier/httpmock"
)

// MockDynamicTransport is a generated httpmock-backed transport for DynamicTransport.
// Routes support a BodyFunc closure for per-request response body generation.
type MockDynamicTransport struct {
	router *httpmock.Router
}

// NewMockDynamicTransport returns a MockDynamicTransport with an empty route table.
func NewMockDynamicTransport() *MockDynamicTransport {
	return &MockDynamicTransport{router: httpmock.NewRouter()}
}

// Route registers a handler for the given method and path pattern.
func (m *MockDynamicTransport) Route(method, path string, handler httpmock.Handler) {
	m.router.Route(method, path, handler)
}

// RouteFunc registers a handler whose body is produced by a closure on each call.
// The closure receives the matched *http.Request and returns an io.Reader.
func (m *MockDynamicTransport) RouteFunc(method, path string, status int, bodyFn func(*http.Request) io.Reader) {
	m.router.RouteFunc(method, path, status, bodyFn)
}

// RoundTrip implements DynamicTransport (and http.RoundTripper).
func (m *MockDynamicTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	return m.router.RoundTrip(req)
}

What the generator did

  • Generated the MockTransport scaffold with a BodyFunc handler field alongside the standard Body field.
  • When BodyFunc is non-nil, the mock calls it on each request to produce the response body. The closure receives the *http.Request so it can vary the response based on query parameters or headers.
  • httpc body closures are called once per attempt; retries are correct by construction because the closure produces a fresh io.Reader on each call.

programmable-router recording-disabled glacier generate

Apache-2.0