Skip to content

memclutter/gorequests

Repository files navigation

gorequests

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.

Release Go Reference Go Report Card Go version CI codecov License: MIT

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()

Contents

Install

go get github.com/memclutter/gorequests

Requires Go 1.18+.

Usage

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.

Request building

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.

Response handling

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.

Middleware

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()

Contributing

Contributions are welcome — see CONTRIBUTING.md for setup, coding conventions, and the commit/PR process. Changes are recorded in CHANGELOG.md.

License

Released under the MIT License.

About

Fluent HTTP client wrapper for Go: build, send, and decode requests in one chain on top of net/http

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors

Languages