https://github.com/goforj/httpx
A modern, generics-first fluent HTTP client for Go - built on req, designed for ergonomic, type-safe APIs with powerful defaults and escape hatches.
https://github.com/goforj/httpx
api-client developer-tools generics go go-library golang http http-client networking req rest typed
Last synced: 11 days ago
JSON representation
A modern, generics-first fluent HTTP client for Go - built on req, designed for ergonomic, type-safe APIs with powerful defaults and escape hatches.
- Host: GitHub
- URL: https://github.com/goforj/httpx
- Owner: goforj
- Created: 2025-12-20T22:03:20.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2025-12-30T05:49:39.000Z (25 days ago)
- Last Synced: 2026-01-01T04:19:38.913Z (23 days ago)
- Topics: api-client, developer-tools, generics, go, go-library, golang, http, http-client, networking, req, rest, typed
- Language: Go
- Homepage:
- Size: 2.92 MB
- Stars: 77
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
A generics-first HTTP client wrapper for Go, built on top of the amazing `github.com/imroc/req/v3` library.
It keeps req's power and escape hatches, while making the 90% use case feel effortless.

## What is httpx?
**httpx** is a modern, ergonomic HTTP client for Go.
It builds on top of the amazing [`req`](https://github.com/imroc/req) library, preserving its flexibility while dramatically reducing boilerplate for common use cases. You get clean defaults, strong typing, and an API designed to stay out of your way.
Think of it as *the 90% solution* - powerful enough for real-world systems, without sacrificing clarity or control.
## Quick Start
```go
type Response struct {
URL string `json:"url"`
}
c := httpx.New(
httpx.BaseURL("https://httpbin.org"),
// ...other options as needed
)
// httpx.Get[T](client, url, options...)
res, err := httpx.Get[Response](c, "/get")
if err != nil {
panic(err) // handle error appropriately
}
fmt.Println(res.URL)
````
## Design Principles
* **Simple by default** - minimal configuration for common cases
* **Composable** - everything is opt-in and chainable
* **Predictable** - no hidden behavior or magic
* **Typed** - first-class generics with zero reflection
* **Escape hatches included** - full access to `req` when needed
## When to Use httpx
Use httpx when you want:
* A clean, expressive HTTP client without boilerplate
* Strong typing without fighting the type system
* Easy composition of headers, params, and behavior
* A smooth path from simple requests to advanced control
If you’re comfortable with `net/http` or `req`, httpx will feel immediately familiar - just faster to write and easier to read.
## Installation
```bash
go get github.com/goforj/httpx
```
## Debugging and Tracing
- `HTTP_TRACE=1` enables request/response dumps for all requests.
- `httpx.EnableDump()` enables dump for a single request.
- `httpx.DumpEachRequest()` enables per-request dumps on a client.
## Documentation
The full API reference below is generated directly from source and always reflects the current codebase.
All runnable examples live in [`./examples`](./examples) and are generated from doc comments.
They are compiled and executed in CI to ensure the documentation stays accurate and up to date.
## Contributing
- Run `go run ./docs/examplegen` after updating doc examples.
- Run `go run ./docs/readme/main.go` to refresh the API index and test count.
- Run `go test ./...`.
## v2 Status
httpx v1 has been tagged and is now frozen. The `main` branch is v2, which includes intentional breaking changes to improve API clarity and ergonomics (for example, request helpers return `(T, error)`).
## API Index
| Group | Functions |
|------:|:-----------|
| **Auth** | [Auth](#auth) [Basic](#basic) [Bearer](#bearer) |
| **Browser Profiles** | [AsChrome](#aschrome) [AsFirefox](#asfirefox) [AsMobile](#asmobile) [AsSafari](#assafari) |
| **Client** | [Default](#default) [New](#new) [Raw](#raw) [Req](#req) |
| **Client Options** | [BaseURL](#baseurl) [CookieJar](#cookiejar) [ErrorMapper](#errormapper) [Middleware](#middleware) [Proxy](#proxy) [ProxyFunc](#proxyfunc) [Redirect](#redirect) [Transport](#transport) |
| **Debugging** | [Dump](#dump) [DumpAll](#dumpall) [DumpEachRequest](#dumpeachrequest) [DumpEachRequestTo](#dumpeachrequestto) [DumpTo](#dumpto) [DumpToFile](#dumptofile) [EnableDump](#enabledump) [Trace](#trace) [TraceAll](#traceall) |
| **Download Options** | [OutputFile](#outputfile) |
| **Errors** | [Error](#error) |
| **Request Composition** | [Body](#body) [Form](#form) [Header](#header) [Headers](#headers) [JSON](#json) [Path](#path) [Paths](#paths) [Queries](#queries) [Query](#query) [UserAgent](#useragent) |
| **Request Control** | [Before](#before) [Timeout](#timeout) |
| **Requests** | [Delete](#delete) [Do](#do) [Get](#get) [Head](#head) [Options](#options) [Patch](#patch) [Post](#post) [Put](#put) |
| **Requests (Context)** | [DeleteCtx](#deletectx) [GetCtx](#getctx) [HeadCtx](#headctx) [OptionsCtx](#optionsctx) [PatchCtx](#patchctx) [PostCtx](#postctx) [PutCtx](#putctx) |
| **Retry** | [RetryBackoff](#retrybackoff) [RetryCondition](#retrycondition) [RetryCount](#retrycount) [RetryFixedInterval](#retryfixedinterval) [RetryHook](#retryhook) [RetryInterval](#retryinterval) |
| **Retry (Client)** | [Retry](#retry) |
| **Upload Options** | [File](#file) [FileBytes](#filebytes) [FileReader](#filereader) [Files](#files) [UploadCallback](#uploadcallback) [UploadCallbackWithInterval](#uploadcallbackwithinterval) [UploadProgress](#uploadprogress) |
| **Advanced** | [TLSFingerprint](#tlsfingerprint) [TLSFingerprintAndroid](#tlsfingerprintandroid) [TLSFingerprintChrome](#tlsfingerprintchrome) [TLSFingerprintEdge](#tlsfingerprintedge) [TLSFingerprintFirefox](#tlsfingerprintfirefox) [TLSFingerprintIOS](#tlsfingerprintios) [TLSFingerprintRandomized](#tlsfingerprintrandomized) [TLSFingerprintSafari](#tlsfingerprintsafari) |
## Auth
Auth sets the Authorization header using a scheme and token.
```go
// Apply to all requests
c := httpx.New(httpx.Auth("Token", "abc123"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Token abc123" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Auth("Token", "abc123"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Token abc123" #string
// }
// }
```
Basic sets HTTP basic authentication headers.
```go
// Apply to all requests
c := httpx.New(httpx.Basic("user", "pass"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Basic dXNlcjpwYXNz" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Basic("user", "pass"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Basic dXNlcjpwYXNz" #string
// }
// }
```
Bearer sets the Authorization header with a bearer token.
```go
// Apply to all requests
c := httpx.New(httpx.Bearer("token"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Bearer token" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Bearer("token"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Authorization => "Bearer token" #string
// }
// }
```
## Browser Profiles
AsChrome applies the Chrome browser profile (headers including User-Agent, TLS, and HTTP/2 behavior).
```go
_ = httpx.New(httpx.AsChrome())
```
AsFirefox applies the Firefox browser profile (headers including User-Agent, TLS, and HTTP/2 behavior).
```go
c := httpx.New(httpx.AsFirefox())
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// User-Agent => "" #string
// }
// }
```
AsMobile applies a mobile Chrome-like profile (headers including User-Agent, TLS, and HTTP/2 behavior).
```go
_ = httpx.New(httpx.AsMobile())
```
AsSafari applies the Safari browser profile (headers including User-Agent, TLS, and HTTP/2 behavior).
```go
_ = httpx.New(httpx.AsSafari())
```
## Client
Default returns the shared default client.
New creates a client with opinionated defaults and optional overrides.
```go
var buf bytes.Buffer
_ = httpx.New(httpx.
BaseURL("https://httpbin.org").
Timeout(5*time.Second).
Header("X-Trace", "1").
Header("Accept", "application/json").
Transport(http.RoundTripper(http.DefaultTransport)).
Middleware(func(_ *req.Client, r *req.Request) error {
r.SetHeader("X-Middleware", "1")
return nil
}).
ErrorMapper(func(resp *req.Response) error {
return fmt.Errorf("status %d", resp.StatusCode)
}).
DumpAll().
DumpEachRequest().
DumpEachRequestTo(&buf).
Retry(func(rc *req.Client) {
rc.SetCommonRetryCount(2)
}).
RetryCount(2).
RetryFixedInterval(200*time.Millisecond).
RetryBackoff(100*time.Millisecond, 2*time.Second).
RetryInterval(func(_ *req.Response, attempt int) time.Duration {
return time.Duration(attempt) * 100 * time.Millisecond
}).
RetryCondition(func(resp *req.Response, _ error) bool {
return resp != nil && resp.StatusCode == 503
}).
RetryHook(func(_ *req.Response, _ error) {}),
)
```
Raw returns the underlying req client for chaining raw requests.
Req returns the underlying req client for advanced usage.
## Client Options
BaseURL sets a base URL on the client.
```go
c := httpx.New(httpx.BaseURL("https://httpbin.org"))
res, _ := httpx.Get[map[string]any](c, "/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
CookieJar sets the cookie jar for the client.
```go
jar, _ := cookiejar.New(nil)
u, _ := url.Parse("https://httpbin.org")
jar.SetCookies(u, []*http.Cookie{
{Name: "session", Value: "abc123"},
})
c := httpx.New(httpx.CookieJar(jar))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/cookies")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// cookies => #map[string]interface {} {
// session => "abc123" #string
// }
// }
```
ErrorMapper sets a custom error mapper for non-2xx responses.
```go
c := httpx.New(httpx.ErrorMapper(func(resp *req.Response) error {
return fmt.Errorf("status %d", resp.StatusCode)
}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/status/500")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
Middleware adds request middleware to the client.
```go
c := httpx.New(httpx.Middleware(func(_ *req.Client, r *req.Request) error {
r.SetHeader("X-Trace", "1")
return nil
}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// X-Trace => "1" #string
// }
// }
```
Proxy sets a proxy URL for the client.
```go
c := httpx.New(httpx.Proxy("http://localhost:8080"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/get")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
ProxyFunc sets a proxy function for the client.
```go
c := httpx.New(httpx.ProxyFunc(http.ProxyFromEnvironment))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
Redirect sets the redirect policy for the client.
```go
c := httpx.New(httpx.Redirect(req.NoRedirectPolicy()))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/redirect/1")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
Transport wraps the underlying transport with a custom RoundTripper.
```go
c := httpx.New(httpx.Transport(http.RoundTripper(http.DefaultTransport)))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
## Debugging
Dump prints values using the bundled godump formatter.
```go
res, _ := httpx.Get[map[string]any](httpx.Default(), "https://httpbin.org/uuid")
httpx.Dump(res)
// #map[string]interface {} {
// uuid => "" #string
// }
```
DumpAll enables req's client-level dump output for all requests.
```go
c := httpx.New(httpx.DumpAll())
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
DumpEachRequest enables request-level dumps for each request on the client.
```go
c := httpx.New(httpx.DumpEachRequest())
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
DumpEachRequestTo enables request-level dumps for each request and writes them to the provided output.
```go
var buf bytes.Buffer
c := httpx.New(httpx.DumpEachRequestTo(&buf))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
_ = buf.String()
```
DumpTo enables req's request-level dump output to a writer.
```go
var buf bytes.Buffer
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.DumpTo(&buf))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
DumpToFile enables req's request-level dump output to a file path.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.DumpToFile("httpx.dump"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
EnableDump enables req's request-level dump output.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.EnableDump())
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
Trace enables req's request-level trace output.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.Trace())
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
TraceAll enables req's client-level trace output for all requests.
```go
c := httpx.New(httpx.TraceAll())
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
## Download Options
OutputFile streams the response body to a file path.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/bytes/1024", httpx.OutputFile("/tmp/file.bin"))
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
## Errors
Error returns a short, human-friendly summary of the HTTP error.
```go
type User struct {
Name string `json:"name"`
}
c := httpx.New()
res, err := httpx.Get[map[string]any](c, "https://httpbin.org/status/404")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
var httpErr *httpx.HTTPError
if errors.As(err, &httpErr) {
_ = httpErr.StatusCode
}
```
## Request Composition
Body sets the request body and infers JSON for structs and maps.
```go
type Payload struct {
Name string `json:"name"`
}
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.Body(Payload{Name: "Ana"}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// json => #map[string]interface {} {
// name => "Ana" #string
// }
// }
```
Form sets form data for the request.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.Form(map[string]string{
"name": "alice",
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// form => #map[string]interface {} {
// name => "alice" #string
// }
// }
```
Header sets a header on a request or client.
```go
// Apply to all requests
c := httpx.New(httpx.Header("X-Trace", "1"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// X-Trace => "1" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Header("X-Trace", "1"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// X-Trace => "1" #string
// }
// }
```
Headers sets multiple headers on a request or client.
```go
// Apply to all requests
c := httpx.New(httpx.Headers(map[string]string{
"X-Trace": "1",
"Accept": "application/json",
}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Accept => "application/json" #string
// X-Trace => "1" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.Headers(map[string]string{
"X-Trace": "1",
"Accept": "application/json",
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// Accept => "application/json" #string
// X-Trace => "1" #string
// }
// }
```
JSON forces JSON encoding for the request body (even when inference might choose differently).
```go
type Payload struct {
Name string `json:"name"`
}
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.JSON(Payload{Name: "Ana"}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// json => #map[string]interface {} {
// name => "Ana" #string
// }
// }
```
Path sets a path parameter by name.
```go
type User struct {
Name string `json:"name"`
}
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/anything/{id}", httpx.Path("id", 42))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// url => "https://httpbin.org/anything/42" #string
// }
```
Paths sets multiple path parameters from a map.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/anything/{org}/users/{id}", httpx.Paths(map[string]any{
"org": "goforj",
"id": 7,
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// url => "https://httpbin.org/anything/goforj/users/7" #string
// }
```
Queries sets query parameters from a map.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/get", httpx.Queries(map[string]string{
"q": "search",
"ok": "1",
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// args => #map[string]interface {} {
// ok => "1" #string
// q => "search" #string
// }
// }
```
Query adds query parameters as key/value pairs.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/get", httpx.Query("q", "search"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// args => #map[string]interface {} {
// q => "search" #string
// }
// }
```
UserAgent sets the User-Agent header on a request or client.
```go
// Apply to all requests
c := httpx.New(httpx.UserAgent("my-app/1.0"))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/headers")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// User-Agent => "my-app/1.0" #string
// }
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/headers", httpx.UserAgent("my-app/1.0"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// User-Agent => "my-app/1.0" #string
// }
// }
```
## Request Control
Before runs a hook before the request is sent.
```go
c := httpx.New()
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/get", httpx.Before(func(r *req.Request) {
r.EnableDump()
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// url => "https://httpbin.org/get" #string
// }
```
Timeout sets a per-request timeout using context cancellation.
```go
// Apply to all requests
c := httpx.New(httpx.Timeout(2 * time.Second))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/delay/2")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/delay/2", httpx.Timeout(2*time.Second))
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
## Requests
Delete issues a DELETE request using the provided client.
```go
type DeleteResponse struct {
URL string `json:"url"`
}
c := httpx.New()
res, err := httpx.Delete[DeleteResponse](c, "https://httpbin.org/delete")
if err != nil {
return
}
httpx.Dump(res) // dumps DeleteResponse
// #DeleteResponse {
// URL => "https://httpbin.org/delete" #string
// }
```
Do executes a pre-configured req request and returns the decoded body and response.
This is the low-level escape hatch when you need full req control.
```go
r := req.C().R().SetHeader("X-Trace", "1")
r.SetURL("https://httpbin.org/headers")
r.Method = http.MethodGet
res, rawResp, err := httpx.Do[map[string]any](r)
if err != nil {
return
}
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// headers => #map[string]interface {} {
// X-Trace => "1" #string
// }
// }
println(rawResp.StatusCode)
```
Get issues a GET request using the provided client.
_Example: bind to a struct_
```go
type GetResponse struct {
URL string `json:"url"`
}
c := httpx.New()
res, _ := httpx.Get[GetResponse](c, "https://httpbin.org/get")
httpx.Dump(res)
// #GetResponse {
// URL => "https://httpbin.org/get" #string
// }
```
_Example: bind to a string body_
```go
resString, _ := httpx.Get[string](c, "https://httpbin.org/uuid")
println(resString) // dumps string
// {
// "uuid": "becbda6d-9950-4966-ae23-0369617ba065"
// }
```
Head issues a HEAD request using the provided client.
```go
c := httpx.New()
_, err := httpx.Head[string](c, "https://httpbin.org/get")
if err != nil {
return
}
```
Options issues an OPTIONS request using the provided client.
```go
c := httpx.New()
_, err := httpx.Options[string](c, "https://httpbin.org/get")
if err != nil {
return
}
```
Patch issues a PATCH request using the provided client.
```go
type UpdateUser struct {
Name string `json:"name"`
}
type UpdateUserResponse struct {
JSON UpdateUser `json:"json"`
}
c := httpx.New()
res, err := httpx.Patch[UpdateUser, UpdateUserResponse](c, "https://httpbin.org/patch", UpdateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps UpdateUserResponse
// #UpdateUserResponse {
// JSON => #UpdateUser {
// Name => "Ana" #string
// }
// }
```
Post issues a POST request using the provided client.
```go
type CreateUser struct {
Name string `json:"name"`
}
type CreateUserResponse struct {
JSON CreateUser `json:"json"`
}
c := httpx.New()
res, err := httpx.Post[CreateUser, CreateUserResponse](c, "https://httpbin.org/post", CreateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps CreateUserResponse
// #CreateUserResponse {
// JSON => #CreateUser {
// Name => "Ana" #string
// }
// }
```
Put issues a PUT request using the provided client.
```go
type UpdateUser struct {
Name string `json:"name"`
}
type UpdateUserResponse struct {
JSON UpdateUser `json:"json"`
}
c := httpx.New()
res, err := httpx.Put[UpdateUser, UpdateUserResponse](c, "https://httpbin.org/put", UpdateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps UpdateUserResponse
// #UpdateUserResponse {
// JSON => #UpdateUser {
// Name => "Ana" #string
// }
// }
```
## Requests (Context)
DeleteCtx issues a DELETE request using the provided client and context.
```go
type DeleteResponse struct {
URL string `json:"url"`
}
ctx := context.Background()
c := httpx.New()
res, err := httpx.DeleteCtx[DeleteResponse](c, ctx, "https://httpbin.org/delete")
if err != nil {
return
}
httpx.Dump(res) // dumps DeleteResponse
// #DeleteResponse {
// URL => "https://httpbin.org/delete" #string
// }
```
GetCtx issues a GET request using the provided client and context.
```go
type GetResponse struct {
URL string `json:"url"`
}
ctx := context.Background()
c := httpx.New()
res, err := httpx.GetCtx[GetResponse](c, ctx, "https://httpbin.org/get")
if err != nil {
return
}
httpx.Dump(res) // dumps GetResponse
// #GetResponse {
// URL => "https://httpbin.org/get" #string
// }
```
HeadCtx issues a HEAD request using the provided client and context.
```go
ctx := context.Background()
c := httpx.New()
_, err := httpx.HeadCtx[string](c, ctx, "https://httpbin.org/get")
if err != nil {
return
}
```
OptionsCtx issues an OPTIONS request using the provided client and context.
```go
ctx := context.Background()
c := httpx.New()
_, err := httpx.OptionsCtx[string](c, ctx, "https://httpbin.org/get")
if err != nil {
return
}
```
PatchCtx issues a PATCH request using the provided client and context.
```go
type UpdateUser struct {
Name string `json:"name"`
}
type UpdateUserResponse struct {
JSON UpdateUser `json:"json"`
}
ctx := context.Background()
c := httpx.New()
res, err := httpx.PatchCtx[UpdateUser, UpdateUserResponse](c, ctx, "https://httpbin.org/patch", UpdateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps UpdateUserResponse
// #UpdateUserResponse {
// JSON => #UpdateUser {
// Name => "Ana" #string
// }
// }
```
PostCtx issues a POST request using the provided client and context.
```go
type CreateUser struct {
Name string `json:"name"`
}
type CreateUserResponse struct {
JSON CreateUser `json:"json"`
}
ctx := context.Background()
c := httpx.New()
res, err := httpx.PostCtx[CreateUser, CreateUserResponse](c, ctx, "https://httpbin.org/post", CreateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps CreateUserResponse
// #CreateUserResponse {
// JSON => #CreateUser {
// Name => "Ana" #string
// }
// }
```
PutCtx issues a PUT request using the provided client and context.
```go
type UpdateUser struct {
Name string `json:"name"`
}
type UpdateUserResponse struct {
JSON UpdateUser `json:"json"`
}
ctx := context.Background()
c := httpx.New()
res, err := httpx.PutCtx[UpdateUser, UpdateUserResponse](c, ctx, "https://httpbin.org/put", UpdateUser{Name: "Ana"})
if err != nil {
return
}
httpx.Dump(res) // dumps UpdateUserResponse
// #UpdateUserResponse {
// JSON => #UpdateUser {
// Name => "Ana" #string
// }
// }
```
## Retry
RetryBackoff sets a capped exponential backoff retry interval for a request.
Overrides the req default interval (fixed 100ms) with jittered backoff.
```go
// Apply to all requests
c := httpx.New(httpx.RetryBackoff(100*time.Millisecond, 2*time.Second))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.RetryBackoff(100*time.Millisecond, 2*time.Second))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
RetryCondition sets the retry condition for a request.
Overrides the default behavior (retry only when a request error occurs).
```go
// Apply to all requests
c := httpx.New(httpx.RetryCondition(func(resp *req.Response, _ error) bool {
return resp != nil && resp.StatusCode == 503
}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/status/503")
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/status/503", httpx.RetryCondition(func(resp *req.Response, _ error) bool {
return resp != nil && resp.StatusCode == 503
}))
httpx.Dump(res) // dumps map[string]any
// map[string]interface {}(nil)
```
RetryCount enables retry for a request and sets the maximum retry count.
Default behavior from req: retries are disabled (count = 0). When enabled,
retries happen only on request errors unless RetryCondition is set, and the
default interval is a fixed 100ms between attempts.
```go
// Apply to all requests
c := httpx.New(httpx.RetryCount(2))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.RetryCount(2))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
RetryFixedInterval sets a fixed retry interval for a request.
Overrides the req default interval (fixed 100ms).
```go
// Apply to all requests
c := httpx.New(httpx.RetryFixedInterval(200 * time.Millisecond))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.RetryFixedInterval(200*time.Millisecond))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
RetryHook registers a retry hook for a request.
Runs before each retry attempt; no hooks are configured by default.
```go
// Apply to all requests
c := httpx.New(httpx.RetryHook(func(_ *req.Response, _ error) {}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.RetryHook(func(_ *req.Response, _ error) {}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
RetryInterval sets a custom retry interval function for a request.
Overrides the req default interval (fixed 100ms).
```go
// Apply to all requests
c := httpx.New(httpx.RetryInterval(func(_ *req.Response, attempt int) time.Duration {
return time.Duration(attempt) * 100 * time.Millisecond
}))
res, _ := httpx.Get[map[string]any](c, "https://httpbin.org/uuid")
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
// Apply to a single request
res, _ = httpx.Get[map[string]any](c, "https://httpbin.org/uuid", httpx.RetryInterval(func(_ *req.Response, attempt int) time.Duration {
return time.Duration(attempt) * 100 * time.Millisecond
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// uuid => "" #string
// }
```
## Retry (Client)
Retry applies a custom retry configuration to the client.
Defaults remain in effect unless the callback modifies them.
```go
_ = httpx.New(httpx.Retry(func(rc *req.Client) {
rc.SetCommonRetryCount(2)
}))
```
## Upload Options
File attaches a file from disk as multipart form data.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.File("file", "/tmp/report.txt"))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "hello" #string
// }
// }
```
FileBytes attaches a file from bytes as multipart form data.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.FileBytes("file", "report.txt", []byte("hello")))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "hello" #string
// }
// }
```
FileReader attaches a file from a reader as multipart form data.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.FileReader("file", "report.txt", strings.NewReader("hello")))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "hello" #string
// }
// }
```
Files attaches multiple files from disk as multipart form data.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil, httpx.Files(map[string]string{
"fileA": "/tmp/a.txt",
"fileB": "/tmp/b.txt",
}))
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// fileA => "hello" #string
// fileB => "world" #string
// }
// }
```
UploadCallback registers a callback for upload progress.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil,
httpx.File("file", "/tmp/report.bin"),
httpx.UploadCallback(func(info req.UploadInfo) {
percent := float64(info.UploadedSize) / float64(info.FileSize) * 100
fmt.Printf("\rprogress: %.1f%%", percent)
if info.FileSize > 0 && info.UploadedSize >= info.FileSize {
fmt.Print("\n")
}
}),
)
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "" #string
// }
// }
```
### UploadCallbackWithInterval
UploadCallbackWithInterval registers a callback for upload progress with a minimum interval.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil,
httpx.File("file", "/tmp/report.bin"),
httpx.UploadCallbackWithInterval(func(info req.UploadInfo) {
percent := float64(info.UploadedSize) / float64(info.FileSize) * 100
fmt.Printf("\rprogress: %.1f%% (%.0f bytes)", percent, float64(info.UploadedSize))
if info.FileSize > 0 && info.UploadedSize >= info.FileSize {
fmt.Print("\n")
}
}, 200*time.Millisecond),
)
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "" #string
// }
// }
```
UploadProgress enables a default progress spinner and bar for uploads.
```go
c := httpx.New()
res, _ := httpx.Post[any, map[string]any](c, "https://httpbin.org/post", nil,
httpx.File("file", "/tmp/report.bin"),
httpx.UploadProgress(),
)
httpx.Dump(res) // dumps map[string]any
// #map[string]interface {} {
// files => #map[string]interface {} {
// file => "" #string
// }
// }
```
## Advanced
TLSFingerprint applies a TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprint(httpx.TLSFingerprintChromeKind))
```
TLSFingerprintAndroid applies the Android TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintAndroid())
```
TLSFingerprintChrome applies the Chrome TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintChrome())
```
TLSFingerprintEdge applies the Edge TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintEdge())
```
TLSFingerprintFirefox applies the Firefox TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintFirefox())
```
TLSFingerprintIOS applies the iOS TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintIOS())
```
TLSFingerprintRandomized applies a randomized TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintRandomized())
```
TLSFingerprintSafari applies the Safari TLS fingerprint preset.
```go
_ = httpx.New(httpx.TLSFingerprintSafari())
```