httpreq

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 2, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

httpreq

JSON-over-HTTP convenience layer on top of net/http. Stdlib-only. One function, one options pattern, no surprises.

import "github.com/ubgo/httpreq"

var resp UserResponse
_, err := httpreq.Do(ctx, "https://api.example.com/users",
    httpreq.WithMethod(http.MethodPost),
    httpreq.WithJSONBody(req),
    httpreq.WithBearerToken(token),
    httpreq.WithTimeout(5 * time.Second),
    httpreq.WithResponseInto(&resp),
)

What it does

  • Builds the request from options.
  • Adds Authorization, Content-Type, custom headers, and query params.
  • Sends with a per-request timeout and your context.
  • Reads the body once.
  • Returns *HTTPError for non-2xx (with the raw body captured).
  • JSON-decodes the body into the target you supplied.

What it doesn't do

  • Retries / backoff / circuit breaking — install those at the transport layer (http.RoundTripper).
  • Streaming responses — for large bodies use net/http directly.
  • GraphQL helpers — those live in separate packages.
  • A global default client — pass WithHTTPClient if you need pooling.

Options

Option Effect
WithMethod(string) HTTP method. Default: GET.
WithHeader(k, v) Add a header. Repeat for multi-value.
WithBearerToken(string) Authorization: Bearer <t>. No-op when empty.
WithQueryParam(k, v) Append a query string parameter. Repeat for multi-value.
WithJSONBody(any) Marshal body as JSON, set Content-Type. nil clears.
WithRawBody([]byte) Send bytes verbatim. Caller sets Content-Type.
WithTimeout(time.Duration) Default: 30s. Set to 0 to use ctx deadline only.
WithHTTPClient(*http.Client) Override the underlying client.
WithResponseInto(any) JSON-decode response into v (must be a pointer).

Error types

Non-2xx responses surface *HTTPError:

_, err := httpreq.Do(ctx, "https://api/x")
var herr *httpreq.HTTPError
if errors.As(err, &herr) {
    log.Printf("status=%d body=%s", herr.StatusCode, herr.Body)
}

Transport errors (DNS, connection, timeout, ctx-cancel) come back as wrapped errors from http.Client. Decode errors are wrapped JSON errors.

License

Apache-2.0 — see LICENSE.

Documentation

Overview

Package httpreq is a small JSON-over-HTTP client convenience layer on top of net/http.

The standard library is fine but verbose for the most common service call: marshal a request body, set headers, send with a timeout, decode a JSON response, and turn non-2xx into an error. This package collapses that into a single options-pattern call:

var resp UserResponse
httpResp, err := httpreq.Do(ctx, "https://api/users",
    httpreq.WithMethod(http.MethodPost),
    httpreq.WithJSONBody(req),
    httpreq.WithBearerToken(token),
    httpreq.WithTimeout(5*time.Second),
    httpreq.WithResponseInto(&resp),
)

What's deliberately NOT here:

  • Retries, circuit breaking, rate limiting. Use a dedicated transport or library for those concerns.
  • GraphQL helpers, Shopify-specific extensions, etc. The lace.io ancestor of this package mixed those in; they have been removed.
  • A global default client. Pass WithHTTPClient explicitly if you want to share connection pools.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Do

func Do(ctx context.Context, endpoint string, opts ...Option) (*http.Response, error)

Do builds and sends the request. The returned *http.Response has its Body already drained and closed; the body bytes have been routed into the option supplied via WithResponseInto, if any.

Non-2xx responses return an *HTTPError so the caller can inspect the raw body. JSON decode errors are wrapped and returned.

Types

type HTTPError

type HTTPError struct {
	StatusCode int
	Status     string
	Body       []byte
}

HTTPError is returned when the response status is outside 2xx. The raw response body is captured in Body so callers can decode their own error shape if needed.

func (*HTTPError) Error

func (e *HTTPError) Error() string

type Option

type Option func(*request) error

Option configures a single request.

func WithBearerToken

func WithBearerToken(token string) Option

WithBearerToken sets `Authorization: Bearer <token>`. No-op if the token is empty.

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient overrides the underlying *http.Client. Use this to share a connection pool across requests or to install custom middleware via a transport. WithTimeout still applies — it sets Client.Timeout if the supplied client has none.

func WithHeader

func WithHeader(key, value string) Option

WithHeader sets a single header. Repeat the option to set multiple. To set repeated values for the same header (e.g. multi-value Accept), call it once per value.

func WithJSONBody

func WithJSONBody(body any) Option

WithJSONBody marshals body as JSON and sets Content-Type: application/json. Pass nil to clear a previously set body.

func WithMethod

func WithMethod(m string) Option

WithMethod sets the HTTP method. Default: GET. Methods are not validated against [http.Method*] constants — the request goes out as you specify it.

func WithQueryParam

func WithQueryParam(key, value string) Option

WithQueryParam appends a URL query parameter. Repeat for multiple values of the same key.

func WithRawBody

func WithRawBody(body []byte) Option

WithRawBody sends body bytes verbatim. Caller must set Content-Type via WithHeader if it matters. Useful for form posts, protobuf, or pre-encoded payloads.

func WithResponseInto

func WithResponseInto(v any) Option

WithResponseInto JSON-decodes the response body into v. v must be a pointer. Skip this option to discard the body.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout caps the total request time including dialing, headers, body, and response reading. Default: 30 seconds. Pass 0 to use the caller's context deadline alone.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL