Skip to content

Request & Response Mutators

Middleware does not touch the underlying request/response objects directly; it reads and writes through mutator interfaces. Middleware always receives the full read-write mutator (RequestMutator / ResponseMutator); the read/write grouping below is for readability only and does not represent separate exported interfaces.

text
RequestMutator  = Read methods  + Write methods
ResponseMutator = Read methods + Write methods
        ↑                                    ↑
  middleware rewrites the request         middleware reads/rewrites the response
  via RequestMutator                      via ResponseMutator

The Handler signature func(ctx, RequestMutator) (ResponseMutator, error) exposes exactly these two mutators as the middleware's entry and exit points.

Request Mutator

Read methods

The following methods read request data. Call them when middleware only needs to inspect request properties.

MethodReturn typeDescription
Method()stringHTTP method
URL()stringRequest URL
Headers()map[string]stringAll request headers
QueryParams()map[string]anyQuery parameters
Body()anyRequest body
Timeout()time.DurationRequest timeout
MaxRetries()intMax retry count
Context()context.ContextRequest context
Cookies()[]http.CookieRequest cookies
FollowRedirects()*boolWhether to follow redirects
MaxRedirects()*intMax redirect count
StreamBody()boolWhether to stream the request body

Write methods

The following methods modify request data. Call them when middleware only needs to modify request properties.

MethodDescription
SetMethod(string)Set the HTTP method
SetURL(string)Set the URL
SetHeaders(map[string]string)Set all request headers
SetHeader(key, value string)Set a single request header
SetQueryParams(map[string]any)Set query parameters
SetBody(any)Set the request body
SetTimeout(time.Duration)Set the timeout
SetMaxRetries(int)Set the max retry count
SetContext(context.Context)Set the context
SetCookies([]http.Cookie)Set cookies
SetFollowRedirects(*bool)Set whether to follow redirects
SetMaxRedirects(*int)Set the max redirect count
SetStreamBody(bool)Set whether to stream

RequestMutator

The read-write request mutator, covering all methods in the Read methods and Write methods tables above. The internal read/write sub-interfaces live in the internal/types package and are not exported separately; externally they are accessed uniformly as RequestMutator. Middleware inspects and rewrites request properties through it before the request is sent.

Response Mutator

Read methods

The following methods read response data.

MethodReturn typeDescription
StatusCode()intStatus code
Status()stringStatus text
Proto()stringProtocol version
Headers()http.HeaderResponse headers
Body()stringResponse body (string)
RawBody()[]byteResponse body (bytes)
ContentLength()int64Content length
Duration()time.DurationRequest duration
Attempts()intAttempt count (including retries)
Cookies()[]*http.CookieResponse cookies
RedirectChain()[]stringRedirect chain
RedirectCount()intRedirect count
RequestHeaders()http.HeaderRequest headers
RequestURL()stringRequest URL
RequestMethod()stringRequest method

Write methods

The following methods modify response data.

MethodDescription
SetStatusCode(int)Set the status code
SetStatus(string)Set the status text
SetProto(string)Set the protocol version
SetHeaders(http.Header)Set response headers
SetBody(string)Set the response body
SetRawBody([]byte)Set the response body (bytes)
SetContentLength(int64)Set the content length
SetDuration(time.Duration)Set the duration
SetAttempts(int)Set the attempt count
SetCookies([]*http.Cookie)Set cookies
SetRedirectChain([]string)Set the redirect chain
SetRedirectCount(int)Set the redirect count
SetRequestHeaders(http.Header)Set request headers
SetRequestURL(string)Set the request URL
SetRequestMethod(string)Set the request method
SetHeader(key string, values ...string)Set a single response header

ResponseMutator

The read-write response mutator, covering all methods in the Read methods and Write methods tables above. The internal read/write sub-interfaces live in the internal/types package and are not exported separately; externally they are accessed uniformly as ResponseMutator. Middleware reads or rewrites the response through it after the request completes — useful for response caching, content transformation (e.g. JSON pretty-printing), encoding/decoding, and response filtering.

Example: Reading and Writing via Mutators

An authentication middleware that injects an auth header via RequestMutator.SetHeader and reads the response status code via ResponseMutator.StatusCode.

go
package main

import (
	"context"
	"fmt"

	"github.com/cybergodev/httpc"
)

// authMiddleware injects an auth header via RequestMutator
// and reads the status code via ResponseMutator
func authMiddleware(token string) httpc.MiddlewareFunc {
	return func(next httpc.Handler) httpc.Handler {
		return func(ctx context.Context, req httpc.RequestMutator) (httpc.ResponseMutator, error) {
			// Write: set a request header via RequestMutator
			req.SetHeader("Authorization", "Bearer "+token)
			// Read: inspect the request method via RequestMutator
			fmt.Printf("Sending %s request\n", req.Method())

			resp, err := next(ctx, req)
			if err != nil {
				return nil, err
			}
			// Read: get the status code via ResponseMutator
			fmt.Printf("Received status code %d\n", resp.StatusCode())
			return resp, nil
		}
	}
}

func main() {
	client, err := httpc.New(&httpc.Config{
		Middleware: &httpc.MiddlewareConfig{
			Middlewares: []httpc.MiddlewareFunc{
				authMiddleware("my-secret-token"),
			},
		},
	})
	if err != nil {
		panic(err)
	}
	defer client.Close()

	result, err := client.Get("https://httpbin.org/get")
	if err != nil {
		panic(err)
	}
	fmt.Println(result.IsSuccess())
	// Sample output:
	// Sending GET request
	// Received status code 200
	// true
}

See Also