Request Options
Request options are functional configuration items passed to request methods via the RequestOption type, enabling fine-grained request control.
result, err := client.Post(url,
httpc.WithJSON(data),
httpc.WithBearerToken(token),
httpc.WithQuery("page", 1),
)All options can be freely combined and are applied in the order they are passed.
Headers
WithHeader
func WithHeader(key, value string) RequestOptionSets a single request header. Keys and values are security-validated (CRLF injection protection).
result, err := client.Get(url,
httpc.WithHeader("X-Custom", "value"),
)WithHeaderMap
func WithHeaderMap(headers map[string]string) RequestOptionSets multiple request headers at once.
result, err := client.Get(url,
httpc.WithHeaderMap(map[string]string{
"Accept": "application/json",
"X-Request-ID": "abc123",
}),
)WithUserAgent
func WithUserAgent(userAgent string) RequestOptionSets the User-Agent header. This is a convenience wrapper for WithHeader("User-Agent", ...).
Authentication
WithBasicAuth
func WithBasicAuth(username, password string) RequestOptionSets HTTP Basic authentication. Username cannot be empty, credentials length is limited.
result, err := client.Get(url,
httpc.WithBasicAuth("admin", "password"),
)WithBearerToken
func WithBearerToken(token string) RequestOptionSets the Authorization: Bearer <token> header. Token cannot be empty.
result, err := client.Get(url,
httpc.WithBearerToken("eyJhbGciOiJIUzI1NiIs..."),
)Request Body
WithJSON
func WithJSON(data any) RequestOptionSets a JSON request body, automatically adding Content-Type: application/json.
result, err := client.Post(url,
httpc.WithJSON(map[string]any{
"name": "test",
"email": "[email protected]",
}),
)WithXML
func WithXML(data any) RequestOptionSets an XML request body, automatically adding Content-Type: application/xml.
WithForm
func WithForm(data map[string]string) RequestOptionSets a URL-encoded form request body, automatically adding Content-Type: application/x-www-form-urlencoded.
result, err := client.Post(url,
httpc.WithForm(map[string]string{
"username": "admin",
"password": "secret",
}),
)WithFormData
func WithFormData(data *FormData) RequestOptionSets a multipart/form-data request body, supporting mixed file and field uploads.
result, err := client.Post(url,
httpc.WithFormData(&httpc.FormData{
Fields: map[string]string{"description": "upload"},
Files: map[string]*httpc.FileData{
"file": {Filename: "doc.pdf", Content: fileBytes},
},
}),
)WithFile
func WithFile(fieldName, filename string, content []byte) RequestOptionConvenient file upload. Automatically builds a multipart request body. Filename is processed for path traversal protection.
result, err := client.Post(url,
httpc.WithFile("upload", "report.csv", csvBytes),
)WithBinary
func WithBinary(data []byte, contentType ...string) RequestOptionSets a binary request body. Default Content-Type is application/octet-stream, customizable.
result, err := client.Post(url,
httpc.WithBinary(imageBytes, "image/png"),
)WithBody
func WithBody(data any, kind ...BodyKind) RequestOptionGeneric request body setting, supporting auto-detection and explicit type specification.
Auto-detection rules (default BodyAuto):
| Input Type | Content-Type |
|---|---|
string | text/plain; charset=utf-8 |
[]byte | application/octet-stream |
map[string]string | application/x-www-form-urlencoded |
*FormData | multipart/form-data |
io.Reader | Not set (handled by caller) |
| Other types | application/json |
Explicit type specification:
// Auto-detect (default)
result, _ := client.Post(url, httpc.WithBody(data))
// Force JSON
result, _ := client.Post(url, httpc.WithBody(data, httpc.BodyJSON))
// Force XML
result, _ := client.Post(url, httpc.WithBody(data, httpc.BodyXML))| Constant | Meaning |
|---|---|
BodyAuto | Auto-detect (default) |
BodyJSON | Force JSON |
BodyXML | Force XML |
BodyForm | Force form |
BodyBinary | Force binary |
BodyMultipart | Force multipart (requires *FormData) |
Query Parameters
WithQuery
func WithQuery(key string, value any) RequestOptionSets a single query parameter.
result, err := client.Get(url,
httpc.WithQuery("page", 1),
httpc.WithQuery("limit", 10),
)WithQueryMap
func WithQueryMap(params map[string]any) RequestOptionSets multiple query parameters at once.
result, err := client.Get(url,
httpc.WithQueryMap(map[string]any{
"page": 1,
"limit": 10,
"sort": "created_at",
}),
)Cookies
WithCookie
func WithCookie(cookie http.Cookie) RequestOptionAdds a single cookie, with security validation.
result, err := client.Get(url,
httpc.WithCookie(http.Cookie{Name: "session", Value: "abc123"}),
)WithCookies
func WithCookies(cookies []http.Cookie) RequestOptionAdds multiple cookies at once. More efficient than calling WithCookie multiple times -- pre-allocates capacity and validates all cookies in a single pass.
cookies := []http.Cookie{
{Name: "session_id", Value: "abc123"},
{Name: "user_pref", Value: "dark_mode"},
{Name: "lang", Value: "en"},
}
result, err := client.Get("https://api.example.com",
httpc.WithCookies(cookies),
)WithCookieMap
func WithCookieMap(cookies map[string]string) RequestOptionAdds simple cookies in bulk. Suitable for scenarios requiring only name-value pairs.
result, err := client.Get(url,
httpc.WithCookieMap(map[string]string{
"session_id": "abc123",
"lang": "en",
}),
)WithCookieString
func WithCookieString(cookieString string) RequestOptionAdds cookies from a raw Cookie header string.
result, err := client.Get(url,
httpc.WithCookieString("session=abc123; lang=en"),
)WithSecureCookie
func WithSecureCookie(securityConfig *CookieSecurityConfig) RequestOptionEnforces validation of request cookie security attributes (Secure, HttpOnly, SameSite).
Option Order
This option only validates cookies that already exist at the time it is applied. You must place WithSecureCookie after all WithCookie/WithCookies/WithCookieMap/WithCookieString calls; otherwise cookies added later will not be validated. For session-level cookie security validation that is not subject to ordering, use SessionManager.SetCookieSecurity.
// Correct order: add cookies first, then validate
result, err := client.Get(url,
httpc.WithCookie(sessionCookie),
httpc.WithCookieMap(otherCookies),
httpc.WithSecureCookie(httpc.StrictCookieSecurityConfig()),
)Request Control
WithContext
func WithContext(ctx context.Context) RequestOptionSets the request context, supporting timeout and cancellation. Context cannot be nil.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
result, err := client.Get(url, httpc.WithContext(ctx))WithTimeout
func WithTimeout(timeout time.Duration) RequestOptionSets a per-request timeout, overriding the client default. Range: 0 to 30 minutes.
result, err := client.Get(url, httpc.WithTimeout(5*time.Second))WithMaxRetries
func WithMaxRetries(maxRetries int) RequestOptionSets the per-request maximum retry count, overriding the client configuration. Range: 0-10.
result, err := client.Get(url, httpc.WithMaxRetries(3))WithFollowRedirects
func WithFollowRedirects(follow bool) RequestOptionControls whether to follow redirects.
// Disable following redirects
result, err := client.Get(url, httpc.WithFollowRedirects(false))WithMaxRedirects
func WithMaxRedirects(maxRedirects int) RequestOptionSets the per-request maximum redirect count. Range: 0-50.
0 Value Semantics
0 does not disable redirects. The engine treats 0 as an "unset" sentinel value and falls back to the default cap (10), so WithMaxRedirects(0) is equivalent to omitting the option. To fully disable redirect following, use WithFollowRedirects(false) instead.
WithAllowPrivateIPs
func WithAllowPrivateIPs(allow bool) RequestOptionOverrides the client's SSRF policy for a single request. When allow is true, the request may access localhost and private/reserved IP ranges (127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 169.254.0.0/16, etc.) and follow redirects to such addresses; when false, SSRF protection is enforced for this request even if the client is configured with Security.AllowPrivateIPs=true.
Security note
This is a per-request escape hatch from SSRF protection, suited for cases where a default-secure client (AllowPrivateIPs=false) occasionally needs to reach internal services, loopback addresses, or a local dev server.
Enable it only when the request URL is trusted and not derived from untrusted user input. To allow internal access for an entire client, set Security.AllowPrivateIPs=true on Config directly.
// Default client blocks private IPs; this call allows it per request
result, err := httpc.Get("http://localhost:8080/health",
httpc.WithAllowPrivateIPs(true),
)WithStreamBody
func WithStreamBody(stream bool) RequestOptionEnables streaming mode; the response body is not cached in memory.
Important Limitation
Streaming mode only takes effect via Download. When used with the standard request methods (Get/Post/Put/Patch/Delete/Head/Options/Request), the response body is read in full and converted into a Result, after which the underlying stream is closed -- the returned Result body is empty and the caller cannot consume the stream.
To actually stream-download large files without caching them in memory, use Download.
Callbacks
WithOnRequest
func WithOnRequest(callback func(req RequestMutator) error) RequestOptionRegisters a pre-send callback. Multiple callbacks can be chained and execute in the order added. Returning an error aborts the request.
result, err := client.Get(url,
httpc.WithOnRequest(func(req httpc.RequestMutator) error {
log.Printf("Sending %s %s", req.Method(), req.URL())
return nil
}),
)WithOnResponse
func WithOnResponse(callback func(resp ResponseMutator) error) RequestOptionRegisters a post-receive callback. Multiple callbacks can be chained and execute in the order added.
result, err := client.Get(url,
httpc.WithOnResponse(func(resp httpc.ResponseMutator) error {
log.Printf("Received response: %d %s", resp.StatusCode(), resp.Status())
return nil
}),
)See Also
- Constants and Types - BodyKind constants and type aliases
- Interface Definitions - RequestMutator, ResponseMutator interfaces
- Request and Response - Request options usage guide