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.
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.
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"
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"),
// Headers
trip.Header("Cache-Control", "no-cache")
trip.UserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; ...")
// Logging
trip.Logger(log.Printf)
trip.Logger(logrus.Infof) // github.com/sirupsen/logrus
trip.Logger(zap.S().Infof) // github.com/uber-go/zap
trip.Logger(zerolog.New(os.Stdout).Printf) // github.com/rs/zerolog
// Retry
trip.Retry(attempts, delay),
trip.Retry(attempts, delay, http.StatusTooManyRequests),
trip.Retry(attempts, delay, trip.RetryableStatusCodes...),
// Idempotency
trip.IdempotencyKey()
),
}
client.Get("http://example.com/")
}
Listed below are some examples how to use Trip for various situations.
func main() {
t := trip.Default(
trip.BearerToken("api-token"),
trip.BasicAuth("username", "password"),
)
client := &http.Client{Transport: t}
client.Get("http://example.com/")
}
func main() {
t := trip.Default(
trip.UserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; ..."),
trip.Header("Cache-Control", "max-age=86400"),
)
client := &http.Client{Transport: t}
client.Get("http://example.com/")
}
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/")
}
func main() {
var (
attempts = 3
delay = 150 * time.Millisecond
)
t := trip.Default(
// Retries 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/")
}
func main() {
t := trip.Default(
trip.Logger(log.Printf),
trip.Logger(logrus.Infof), // github.com/sirupsen/logrus
trip.Logger(zap.S().Infof), // github.com/uber-go/zap
trip.Logger(zerolog.New(os.Stdout).Printf), // github.com/rs/zerolog
)
client := &http.Client{Transport: t}
client.Get("http://example.com/")
// Example message:
// POST http://example.com/ - 200 OK - 12.34ms
}
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/")
}
func main() {
t := trip.Default(
trip.BearerToken("api-token"),
)
http.DefaultClient.Transport = t
http.Get("http://example.com/")
}
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
}
If you like to contribute to Trip by adding new features, improving the documentation or fixing bugs, feel free to open a new issue.