httpr

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Dec 17, 2024 License: MIT Imports: 5 Imported by: 0

README

httpr

Go Reference

HTTP transport with retries

This module provides a transport (http.RoundTripper) with retry functionality that can be used with the standard library HTTP client.

Getting started

Prerequisites
  • Go 1.18
Install
go get github.com/KarlGW/httpr

Alternative:

git clone git@github.com:KarlGW/httpr.git # git clone https://github.com/KarlGW/httpr.git
mkdir /path/to/project/httpr
cp httpr/*.go /path/to/project/httpr
Examples

Setting up the transport with the default retry policy:

package main

import (
    "net/http"
    "time"

    "github.com/KarlGW/httpr"
)

func main() {
    client := &http.Client{
        Transport: httpr.New(), // httpr.NewTransport also works for clarity.
    }

    req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
    if err != nil {
        // Handle error.
    }

    resp, err := client.Do(req)
    if err != nil {
        // Handle error.
    }
}

Setting up the transport with a custom retry policy:

package main

import (
    "net/http"
    "time"

    "github.com/KarlGW/httpr"
)

func main() {
    client := &http.Client{
        Transport: httpr.New(httpr.WithRetryPolicy(
            httpr.RetryPolicy{
                ShouldRetry: httpr.StandardShouldRetry,
                Backoff:     httpr.ExponentialBackoff(),
                MaxRetries:  3,
                MinDelay:    500 * time.Milliseconds,
                MaxDelay:    5 * time.Seconds,
                Jitter:      0.2,
            }
        )),
    }

    req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
    if err != nil {
        // Handle error.
    }

    resp, err := client.Do(req)
    if err != nil {
        // Handle error.
    }
}

Usage

Retry policy

By default the http.Transport is configured with a default policy of:

httpr.RetryPolicy{
    ShouldRetry: httpr.StandardShouldRetry,
    Backoff:     httpr.ExponentialBackoff(),
    MaxRetries:  3,
    MinDelay:    500 * time.Milliseconds,
    MaxDelay:    5 * time.Seconds,
    Jitter:      0.2,
}

Which means that it will retry on client errors and HTTP statuses 408, 429, 500, 502, 503 and 504 with exponential backoff with 3 max retries. The backoff begins with 500 milliseconds and will double between each attempt with a maximum final duration of 5 seconds. The jitter adds some randomness to the backoff.

Additional transports

If another transport (http.RoundTripper) should be used as the underlying transport (transport chaining), it can be provided with the option WithTransport.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var NewTransport = New

NewTansport creates and configures a new transport. If no retry policy is provided a default one will be set.

The default retry policy has retries with exponential backoff with the foloowing values:

MaxRetries: 3, MinDelay: 500ms, MaxDelay: 5s and Jitter: 0.2

It retries on client errors and HTTP statuses: 408, 429, 500, 502, 503 and 504.

Functions

func ExponentialBackoff

func ExponentialBackoff() func(minDelay, maxDelay time.Duration, jitter float64) time.Duration

ExponentialBackoff provides backoff with an increasing delay from min delay, to max delay with jitter.

func StandardShouldRetry

func StandardShouldRetry(r *http.Response, err error) bool

StandardShouldRetry is a standard implementation of ShouldRetry. It will retry on client errors and on response errors with status codes: 408, 429, 500, 502, 503 and 504.

Types

type Backoff

type Backoff func(minDelay, maxDelay time.Duration, jitter float64) time.Duration

Backoff is a function that provides delays between retries with backoff.

type Option

type Option func(t *Transport)

Option is a function that configures the Transport.

func WithNoRetries added in v0.2.0

func WithNoRetries() Option

WithNoRetries configures the transport to not perform any retries.

func WithRetryPolicy

func WithRetryPolicy(retryPolicy RetryPolicy) Option

WithRetryPolicy sets the retry policy for the transport.

func WithTransport

func WithTransport(transport http.RoundTripper) Option

WithTransport sets the underlying transport. Use when other custom transports are needed.

type RetryPolicy

type RetryPolicy struct {
	// ShouldRetry is a function that evaluates if a retry should be done.
	ShouldRetry ShouldRetry
	// Backoff is a function that provides backoff between retries.
	Backoff Backoff
	// MaxRetries is the maximum amount of retries.
	MaxRetries int
	// MinDelay for the backoff.
	MinDelay time.Duration
	// MaxDelay for the backoff.
	MaxDelay time.Duration
	// Jitter for the backoff. A small number is recommended (0.1-0.2).
	Jitter float64
}

RetryPolicy contains rules for retries.

func (RetryPolicy) IsZero

func (r RetryPolicy) IsZero() bool

IsZero returns true if the RetryPolicy is the zero value.

type ShouldRetry

type ShouldRetry func(r *http.Response, err error) bool

ShouldRetry is a function that evaluates if a retry should be done.

type Transport

type Transport struct {
	// contains filtered or unexported fields
}

Transport is a transport that provides retry functionality.

Example (Create)
package main

import (
	"fmt"
	"io"
	"net/http"

	"github.com/KarlGW/httpr"
)

func main() {
	// Setup an HTTP client with the httpr Transport. When using a struct
	// literal the default retry policy is used.
	client := &http.Client{
		Transport: &httpr.Transport{},
	}

	req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
	if err != nil {
		// Handle error.
	}

	resp, err := client.Do(req)
	if err != nil {
		// Handle err.
	}
	defer resp.Body.Close()

	b, err := io.ReadAll(req.Body)
	if err != nil {
		// Handle err.
	}
	fmt.Println(string(b))
}

func New

func New(options ...Option) *Transport

New creates and configures a new transport. If no retry policy is provided a default one will be set.

The default retry policy has retries with exponential backoff with the foloowing values:

MaxRetries: 3, MinDelay: 500ms, MaxDelay: 5s and Jitter: 0.2

It retries on client errors and HTTP statuses: 408, 429, 500, 502, 503 and 504.

Example
package main

import (
	"fmt"
	"io"
	"net/http"

	"github.com/KarlGW/httpr"
)

func main() {
	// Setup an HTTP client with the httpr Transport with the default retry policy.
	client := &http.Client{
		Transport: httpr.New(),
	}

	req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
	if err != nil {
		// Handle error.
	}

	resp, err := client.Do(req)
	if err != nil {
		// Handle err.
	}
	defer resp.Body.Close()

	b, err := io.ReadAll(req.Body)
	if err != nil {
		// Handle err.
	}
	fmt.Println(string(b))
}
Example (WithOptions)
package main

import (
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/KarlGW/httpr"
)

func main() {
	// Setup an HTTP client with the httpr Transport with a custom retry policy.
	client := &http.Client{
		Transport: httpr.New(httpr.WithRetryPolicy(httpr.RetryPolicy{
			ShouldRetry: httpr.StandardShouldRetry,
			Backoff:     httpr.ExponentialBackoff(),
			MaxRetries:  3,
			MinDelay:    500 * time.Millisecond,
			MaxDelay:    5 * time.Second,
			Jitter:      0.2,
		})),
	}

	req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
	if err != nil {
		// Handle error.
	}

	resp, err := client.Do(req)
	if err != nil {
		// Handle err.
	}
	defer resp.Body.Close()

	b, err := io.ReadAll(req.Body)
	if err != nil {
		// Handle err.
	}
	fmt.Println(string(b))
}

func (*Transport) RoundTrip

func (tr *Transport) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip satisfies the http.RoundTripper interface and performs an http request with the configured retry policy.

func (*Transport) Set added in v0.2.0

func (tr *Transport) Set(options ...Option)

Set configures the transport with the provided options.

Jump to

Keyboard shortcuts

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