trip

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2023 License: MIT Imports: 6 Imported by: 10

Image README

Trip

Go Reference Go Report Card MIT Release

Elegant middleware functions for your HTTP clients.


Trip is the enhancement for your HTTP clients:

  • Authorize HTTP requests once and for all.
  • Make requests more resilient against temporary failures.
  • Removes clutter from your HTTP calls.
  • Plugs easily into your existing HTTP clients.
  • Zero dependencies.
  • Tiny and readable codebase.

Concepts

Trip is aimed to be used with the HTTP client and act as a middleware before any request goes out.

In a nutshell, the http.Client builds the HTTP request with its headers and body and hands it over to the transport. The transport then sends it off to the server and waits for the response. Once it got the response, it gives it back to the http.Client.

Trip intercepts the hand-over part between client and transport and can modify the request before it goes out. It can also inspect the response and take action like retrying a request on network errors.

Installation

Trip requires Go 1.18 or higher. Use go get to install the library.

go get -u github.com/philippta/trip@latest

Next, import it into your application:

import "github.com/philippta/trip"

Usage

Trip can be easily used with any http.Client by creating a new instance and setting it as the Transport of the client.

package main

import (
    "net/http"

    "github.com/philippta/trip"
)

func main() {
    var (
        attempts = 3
        delay    = 50 * time.Millisecond
    )

    client := &http.Client{
        Transport: trip.Default(
            // Auth
            trip.BearerToken("api-token"),
            trip.BasicAuth("username", "password"),

            // Retry
            trip.Retry(attempts, delay),
            trip.Retry(attempts, delay, http.StatusTooManyRequests),
            trip.Retry(attempts, delay, trip.RetryableStatusCodes...),

            // Idempotency
            trip.ItempotencyKey()

            // Headers
            trip.Header("Cache-Control", "no-cache")
            trip.UserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; ...")
        ),
    }

    client.Get("http://example.com/")
}

Examples

Listed below are some examples how to use Trip for various situations.

Authentication with Bearer Token
func main() {
    t := trip.Default(
        trip.BearerToken("api-token"),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Authentication with HTTP Basic Auth
func main() {
    t := trip.Default(
        trip.BasicAuth("username", "password"),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Applying custom User-Agents
func main() {
    t := trip.Default(
        trip.UserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; ..."),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Applying custom Header fields
func main() {
    t := trip.Default(
        trip.Header("X-Foo", "bar"),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Retries for flaky networks or API servers
func main() {
    var (
        attempts = 3
        delay    = 150 * time.Millisecond
    )

    t := trip.Default(
        // Retries connection failures
        trip.Retry(attempts, retryDelay),

        // Retries connection failures and status codes
        trip.Retry(attempts, retryDelay, http.StatusTooManyRequests),

        // Retries connection failures and common retryable status codes
        trip.Retry(attempts, retryDelay, trip.RetryableStatusCodes...),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Retrying with Idempotency Keys
func main() {
    var (
        attempts = 3
        delay    = 150 * time.Millisecond
    )

    t := trip.Default(
        // Retries only connection failures
        trip.Retry(attempts, retryDelay),

        // Generates idempotency keys for POST and PATCH requests
        trip.IdempotencyKey(),
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Adding custom interceptors
func main() {
    t := trip.Default(
        func (next http.RoundTripper) http.RoundTripper {
            return trip.RoundTripFunc(func(r *http.Request) (http.Response, error) {
                // before request
                resp, err := next.RoundTrip(r)
                // after request
                return resp, err
            })
        }
    )

    client := &http.Client{Transport: t}
    client.Get("http://example.com/")
}
Extending the default HTTP client
func main() {
    t := trip.Default(
        trip.BearerToken("api-token"),
    )

    http.DefaultClient.Transport = t
    http.Get("http://example.com/")
}

Retryable HTTP Status Codes

trip.RetryableStatusCodes holds a list of common HTTP status codes that are considered temporary and can be retried.

trip.RetryableStatusCodes = []int{
	http.StatusRequestTimeout,      // 408
	http.StatusTooEarly,            // 425
	http.StatusTooManyRequests,     // 429
	http.StatusInternalServerError, // 500
	http.StatusBadGateway,          // 502
	http.StatusServiceUnavailable,  // 503
	http.StatusGatewayTimeout,      // 504
}

Contributing

If you like to contribute to Trip by adding new features, improving the documentation or fixing bugs, feel free to open a new issue.

Image Documentation

Index

Examples

Constants

This section is empty.

Variables

RetryableStatusCodes contains common HTTP status codes that are considered temporary and can be retried.

Functions

func Default

func Default(trips ...TripFunc) http.RoundTripper

Default creates a new http.RoundTripper based on http.DefaultTransport.

Example
package main

import (
	"net/http"
	"os"
	"time"

	"github.com/philippta/trip"
)

func main() {
	var (
		attempts = 3
		delay    = 50 * time.Millisecond
		apiToken = os.Getenv("API_TOKEN")
	)

	client := &http.Client{
		Transport: trip.Default(
			trip.BearerToken(apiToken),
			trip.Retry(attempts, delay, trip.RetryableStatusCodes...),
		),
	}

	client.Get("https://api.example.com/endpoint")
}

func New

func New(transport http.RoundTripper, trips ...TripFunc) http.RoundTripper

New creates a new http.RoundTripper by wrapping a given transport with the provided middleware/trip functions. If transport is nil, the http.DefaultTransport is used.

Types

type RoundTripperFunc

type RoundTripperFunc func(*http.Request) (*http.Response, error)

RoundTripperFunc implements http.RoundTripper for convenient usage.

func (RoundTripperFunc) RoundTrip

func (fn RoundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip satisfies http.RoundTripper and calls fn.

type TripFunc

type TripFunc func(http.RoundTripper) http.RoundTripper

TripFunc is function for wrapping http.RoundTrippers.

func BasicAuth

func BasicAuth(username, password string) TripFunc

BasicAuth sets the `Authorization` header on every request to `Basic <encoded-username-and-password>`.

func BearerToken

func BearerToken(token string) TripFunc

BearerToken sets the `Authorization` header on every request to `Bearer <token>`.

func Header(key, value string) TripFunc

Header sets a header field on every request to the given value.

func IdempotencyKey added in v0.2.0

func IdempotencyKey() TripFunc

IdempotencyKey generates a random string for POST and PATCH requests and sets it as the `Idempotency-Key` header. If used in conjunction with Retry, this function should be applied after Retry.

func Retry

func Retry(attempts int, delay time.Duration, statusCodes ...int) TripFunc

Retry retries a failed HTTP request a given number of times and applies a fixed delay inbetween calls. Optionally a list of HTTP status codes can be provided that are considered as failure case. This can be used in combination with RetryableStatusCodes.

func UserAgent added in v0.2.0

func UserAgent(agent string) TripFunc

UserAgent sets the `User-Agent` header on every request to the given user agent.

Jump to

Keyboard shortcuts

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