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/gorequestsRequires 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.