rester

package module
v2.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2024 License: MIT Imports: 21 Imported by: 2

README

Rester

Easy http for the REST of us

Goals

  1. Build a library that makes writing REST clients much less tedious.
  2. Lots of sugar on common crap for rest calls.
  3. Tripperware to catch common functionality and be more helpful (like returning an error for 400/500 class errors).
  4. Dynamic updates to e.g. base URLs if/when configuration changes in realtime.

Example

root := rester.Must(rester.New("apis.example.com"))
root.Transport = rester.All{
  rester.MaxStatus(399), // Return an actual error which includes the code and body if the res.Status is 400/500
  rester.Logging(logrus.WithField("client", "gitlab")), // Log requests
}.Wrap(http.DefaultTransport)

apiv1 := rester.Must(client.Sub("/api/v1"))
in := input{Foo: "foo", ID: 1234}
var out foo
err := apiv1.R().Post("foo").JSON(in).Do(context.Background()).JSON(&out)

Documentation

Overview

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"github.com/sirupsen/logrus"
)

var (
	root     = Must(New("https://gitlab.aexp.com"))
	v4       = Must(root.Sub("api/v4"))
	issues   = Must(v4.Sub("issues"))
	projects = Must(v4.Sub("projects"))
)

func init() {
	root.Transport = All{
		MaxStatus(399),
		Logging(logrus.WithField("client", "gitlab")),
	}.Wrap(http.DefaultTransport)
}

func main() {
	var is []interface{}

	ctx := context.Background()
	if err := issues.R().Do(ctx).JSON(&is); err != nil {
		log.Fatal(err)
	}

	if err := issues.R().Get("sub").Do(ctx).JSON(&is); err != nil {
		log.Fatal(err)
	}

	if err := issues.R().Get("sub/%d", 3).Do(ctx).JSON(&is); err != nil {
		log.Fatal(err)
	}

	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "https://foobar.aexp.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	res, err := projects.do(req)
	if err != nil {
		log.Fatal(err)
	}
	res.Body.Close()

	fmt.Println(len(is))
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// DefaultMerger is the Merger used unless a client has one specified.
	DefaultMerger = MergeFunc(BasicMerge)
)
View Source
var (
	// DefaultTransport is the fallback transport mechanism for when a transport
	// is unspecified.
	DefaultTransport = http.DefaultTransport
)

Any URLMerger can merge a URL

Functions

func BasicMerge

func BasicMerge(a, b *url.URL) *url.URL

BasicMerge is a MergeFunc that does (believe it or not) a basic URL merge. Path and query are merged, and all else comes from the left (`a`) URL.

func ReqFunc

func ReqFunc[I, O any](c *Client, path, verb string) func(ctx context.Context, in I) (*O, error)

ReqFunc is a quick generic shorthand for turning a Client+Path+Verb and two types into a function that takes I and returns O, error

Types

type All

type All []Tripperware

All is a slice of Tripperwares that applies all of them in order.

func (All) Wrap

func (a All) Wrap(rt http.RoundTripper) http.RoundTripper

Wrap simply iterates and applies each roundtripper as a wrapper.

type BadStatusErr

type BadStatusErr struct {
	Max, Actual int
	Status      string
	Body        []byte
}

func (*BadStatusErr) Error

func (b *BadStatusErr) Error() string

type Client

type Client struct {
	Parent    *Client
	Path      *url.URL
	Transport http.RoundTripper
	Merger    URLMerger
}

A Client is the basis for a very basic HTTP RESTful client with helpers.

func Must

func Must(c *Client, e error) *Client

Must returns the Client and panics if the error is non-nil.

func New

func New(format string, args ...interface{}) (*Client, error)

New returns a bas Client, or any errors from parsing the URL base.

func (*Client) Flat

func (c *Client) Flat() *Client

Flat flattens out the parent hierarchy and decouples the Client from any parent changes. It will also effectively cache the parent URL hierarchy. Can be done if performance is critical or dynamic updates are not desired, or to deliberately decouple from another service.

func (*Client) R

func (c *Client) R() *Request

func (*Client) Sub

func (c *Client) Sub(subPath string) (*Client, error)

Sub returns a client scoped to a subresource

func (*Client) Subf

func (c *Client) Subf(format string, args ...interface{}) (*Client, error)

Subf returns a client scoped to a subresource, with Sprintf'd args

type DefaultHeaders

type DefaultHeaders http.Header

DefaultHeaders simplifies setting headers on an outgoing request if they were not already set.

func (DefaultHeaders) Wrap

Wrap sets all headers that weren't already set on the outgoing request before performing it

type MaxStatus

type MaxStatus int

func (MaxStatus) Wrap

type MergeFunc

type MergeFunc func(a, b *url.URL) *url.URL

MergeFunc implements merging by calling a variadic

func (MergeFunc) MergeURLs

func (m MergeFunc) MergeURLs(urls []*url.URL) *url.URL

MergeURLs implements URLMerger left-to-right

type MergeHeaders

type MergeHeaders http.Header

MergeHeaders simplifies replacing all headers on an outgoing request.

func (MergeHeaders) Wrap

Wrap appends slices together to merge headers

type ReplaceHeaders

type ReplaceHeaders http.Header

ReplaceHeaders simplifies replacing all headers on an outgoing request.

func (ReplaceHeaders) Wrap

Wrap replaces all headers on the outgoing request before performing it

type Request

type Request struct {
	Body   io.Reader
	Method string
	Header http.Header
	Query  url.Values
	// contains filtered or unexported fields
}

func (*Request) Delete

func (r *Request) Delete(fmt string, args ...interface{}) *Request

func (*Request) Do

func (r *Request) Do(ctx context.Context) *Response

func (*Request) Get

func (r *Request) Get(fmt string, args ...interface{}) *Request

func (*Request) JSON

func (r *Request) JSON(ifc interface{}) *Request

func (*Request) Patch

func (r *Request) Patch(fmt string, args ...interface{}) *Request

func (*Request) Post

func (r *Request) Post(fmt string, args ...interface{}) *Request

func (*Request) Put

func (r *Request) Put(fmt string, args ...interface{}) *Request

func (*Request) SetHeader

func (r *Request) SetHeader(k, v string) *Request

func (*Request) SetQuery

func (r *Request) SetQuery(k, v string) *Request

SetQuery will set a key/value pair in the URL query params for the final request. It will override any colliding values in the fmt.

func (*Request) WithBasicAuth

func (r *Request) WithBasicAuth(user, pass string) *Request

WithBasicAuth sets up basic auth headers on the request.

func (*Request) WithBody

func (r *Request) WithBody(rd io.Reader) *Request

WithBody sets the eventual Request body to be the given io.Reader

func (*Request) WithHeader

func (r *Request) WithHeader(h http.Header) *Request

func (*Request) WithMethod

func (r *Request) WithMethod(m string) *Request

WithMethod sets the request method to be the given method.

func (*Request) WithQuery

func (r *Request) WithQuery(v url.Values) *Request

WithQuery will set a url.Values in the URL query params for the final request. It will override any colliding values in the fmt.

type RequestFunc

type RequestFunc func(*http.Request) error

A RequestFunc is an implementation of Tripperware that simply modifies a request before it is RoundTripped.

func BasicAuth

func BasicAuth(u, p string) RequestFunc

BasicAuth returns a Tripperware that adds basic auth to a request.

func (RequestFunc) Wrap

Wrap modifies the request prior to RoundTripping it.

type Response

type Response struct {
	io.ReadCloser
	HTTP *http.Response
}

func (Response) Err

func (r Response) Err() error

func (Response) JSON

func (r Response) JSON(ifc interface{}) error

func (Response) XML

func (r Response) XML(ifc interface{}) error

type ResponseFunc

type ResponseFunc func(*http.Response) (*http.Response, error)

A ResponseFunc is an implementation of Tripperware that only modifies a response once it is RoundTripped.

func (ResponseFunc) Wrap

type Tripperware

type Tripperware interface {
	Wrap(rt http.RoundTripper) http.RoundTripper
}

A Tripperware can implement some specific functionality around request/response/errors.

func Logging

func Logging(entry *logrus.Entry) Tripperware

Logging returns a Tripperware that logs client requests.

func Metrics

func Metrics() Tripperware

Metrics returns a Tripperware that instruments prometheus metrics. The following metrics are provided:

http_tripper_started_requests_total - counter
http_tripper_completed_requests_total - counter
http_tripper_completed_latency_seconds - histogram
http_tripper_request_size_bytes - histogram
http_tripper_response_size_bytes - histogram

func OAuth added in v2.3.0

func OAuth(ts oauth2.TokenSource) Tripperware

OAuth wraps an oauth2.TokenSource to provide a Tripperware that adds the token to the request.

func WithTrace

func WithTrace(tr opentracing.Tracer) Tripperware

WithTrace starts a span for all outgoing requests, and injects that span into the ougoing request http headers, and records tags for both request and response if necessary.

func Zerologger added in v2.5.0

func Zerologger(z *zerolog.Logger) Tripperware

Zerologger returns a Tripperware that logs client requests with some helpful standard information using zerolog.

type TripperwareFunc

type TripperwareFunc func(rt http.RoundTripper) http.RoundTripper

A TripperwareFunc is the typical one-liner func implementation of a single-method interface.

func Backoff

func Backoff(b backoff.BackOff) TripperwareFunc

Backoff wraps a cenkalti Backoff policy with a middleware that attempts multiple times to perform a request, returning immediately if the error is a code 4xx.

func (TripperwareFunc) Wrap

Wrap calls the func to implement Tripperware.

type URLMerger

type URLMerger interface {
	MergeURLs(urls []*url.URL) *url.URL
}

A URLMerger implements a strategy for merging multiple URLs

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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