Package retry is a small implementation of the http.RoundTripper
interface
that can be found in http.Client
. It is responsible to make HTTP requests
and can be used to cache or retry them.
By default a request will be tried again only if the response code is below
500 (Internal Server Error) and not 429 (Too Many Requests). This behaviour
can be changed with the WithVerifier
option.
Create a new HTTP client that will retry requests five times and sleeps one second between each one. Since the requested URL will always return a status code of 500 (Internal Server Error), this function will run for five seconds and the time it takes to call the endpoint five times.
package main
import (
"fmt"
"github.com/bake/retry"
"io"
"log"
"net/http"
"os"
"time"
)
func main() {
client := &http.Client{
Transport: retry.New(5, time.Second),
}
res, err := client.Get("https://httpbin.org/status/500")
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
fmt.Printf("%s\n", res.Status)
if _, err := io.Copy(os.Stdout, res.Body); err != nil {
log.Fatal(err)
}
}
WithVerifier can be used to modify the default behaviour that is used to determine if a request can be repeated. In this example, all responses that do not succeed (with a status code outside [200-300[) will be tried again.
package main
import (
"fmt"
"github.com/bake/retry"
"io"
"log"
"net/http"
"os"
"time"
)
func main() {
verifier := func(res *http.Response) bool {
return 200 > res.StatusCode || res.StatusCode >= 300
}
client := &http.Client{
Transport: retry.New(5, time.Second, retry.WithVerifier(verifier)),
}
res, err := client.Get("https://httpbin.org/status/418")
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
fmt.Printf("%s\n", res.Status)
if _, err := io.Copy(os.Stdout, res.Body); err != nil {
log.Fatal(err)
}
}