A fluent HTTP client wrapper for Go — build a request, set the body, assert the status code, and decode the response in a single readable chain, on top of the standard
net/http.
The standard library's HTTP client is powerful but verbose: a single
GET-and-decode-JSON call means creating a request, doing it, deferring a body
close, reading the body, checking the status, and unmarshalling — every time.
gorequests collapses that into one chain and keeps cross-cutting concerns
(proxying, retries) out of the core, as opt-in middleware.
var out map[string]string err := gorequests.Get("https://api.ipify.org?format=json"). ResponseCodeOk(http.StatusOK). ResponseJson(&out). Exec()
go get github.com/memclutter/gorequests
Requires Go 1.18+.
Start a request with a verb helper (Get, Post, Put, Delete, Patch,
Head, Options, Trace, Connect) or with Requests() for full control,
then chain configuration and finish with Exec():
import ( "net/http" "net/url" "github.com/memclutter/gorequests" ) // GET with a templated URL and JSON decoding. var user User err := gorequests.Get("https://api.example.com/users/%d", id). Header("Authorization", "Bearer "+token). ResponseCodeOk(http.StatusOK). ResponseJson(&user). Exec() // POST a JSON body. err = gorequests.Post("https://api.example.com/users"). Json(map[string]any{"name": "Ada"}). ResponseCodeOk(http.StatusCreated). Exec() // POST a form. err = gorequests.Post("https://api.example.com/login"). Form(url.Values{"user": {"ada"}, "pass": {"secret"}}). Exec()
The URL passed to Url (and the verb helpers) is run through fmt.Sprintf, so
path and query parameters can be templated inline.
| Method | Effect |
|---|---|
Method(verb) |
Set the HTTP method. |
Url(format, args...) |
Set the URL, formatted via fmt.Sprintf. |
Header(key, value) |
Add a header (repeatable; values accumulate). |
Cookies(...*http.Cookie) |
Attach cookies. |
Data(bytes, contentType...) |
Raw request body with an optional content type. |
Form(url.Values) |
Form body; sets application/x-www-form-urlencoded. |
Json(value) |
JSON body; marshals value and sets application/json. |
When more than one body is set, raw Data is used if present; otherwise Form
takes precedence over Json.
| Method | Effect |
|---|---|
ResponseCodeOk(...int) |
Whitelist of acceptable status codes; any other status is an error. |
ResponseCodeFail(...int) |
Blacklist of failing status codes; a match is an error. |
ResponseRaw(*[]byte) |
Capture the raw response body. |
ResponseJson(value) |
Unmarshal the JSON response body into value. |
Exec() |
Send the request and apply the response handling; returns error. |
Cross-cutting behaviour is added with Use(...), which accepts any value
implementing one of two interfaces:
type ClientOverrideMiddleware interface { ClientOverride(c *http.Client) (*http.Client, error) } type RequestOverrideMiddleware interface { RequestOverride(r *http.Request) (*http.Request, error) }
Client overrides run while the client is built; request overrides run just before the request is sent. Two middlewares ship as separate modules and compose in the same chain:
import ( gorequests_proxy "github.com/memclutter/gorequests-proxy" gorequests_retry "github.com/memclutter/gorequests-retry" ) err := gorequests.Get("https://api.example.com/"). Use(&gorequests_retry.Retry{RetryMax: 3}). Use(&gorequests_proxy.Proxy{Proxies: []string{"http://user:pass@host:3128"}}). ResponseCodeOk(http.StatusOK). Exec()
- gorequests-proxy — route through an HTTP(S) or SOCKS proxy.
- gorequests-retry — retry on network errors and configured status codes.
Contributions are welcome — see CONTRIBUTING.md for setup, coding conventions, and the commit/PR process. Changes are recorded in CHANGELOG.md.
Released under the MIT License.