diff --git a/hack/failserver/main.go b/hack/failserver/main.go index 6d936d17..e0eaaa35 100644 --- a/hack/failserver/main.go +++ b/hack/failserver/main.go @@ -1,9 +1,14 @@ package main -import "net/http" +import ( + "io" + "net/http" + "os" +) func main() { http.ListenAndServe(":8081", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.Copy(os.Stdout, r.Body) w.WriteHeader(http.StatusServiceUnavailable) w.Write([]byte("unavailable\n")) })) diff --git a/hack/retryproxy/main.go b/hack/retryproxy/main.go index d3e49ada..64534549 100644 --- a/hack/retryproxy/main.go +++ b/hack/retryproxy/main.go @@ -1,7 +1,9 @@ package main import ( + "bytes" "errors" + "io" "log" "net/http" "net/http/httputil" @@ -9,40 +11,53 @@ import ( ) func main() { - // go run ./hack/failserver - u1, err := url.Parse("http://localhost:8081") - if err != nil { - panic(err) - } - p1 := httputil.NewSingleHostReverseProxy(u1) + http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + panic(err) + } + r.Body.Close() - // go run ./hack/successserver - u2, err := url.Parse("http://localhost:8082") - if err != nil { - panic(err) - } - p2 := httputil.NewSingleHostReverseProxy(u2) + // go run ./hack/failserver + first := newReverseProxy("http://localhost:8081") - p1.ModifyResponse = func(r *http.Response) error { - if r.StatusCode == http.StatusServiceUnavailable { - // Returning an error will trigger the ErrorHandler. - return errRetry + first.ModifyResponse = func(r *http.Response) error { + if r.StatusCode == http.StatusServiceUnavailable { + // Returning an error will trigger the ErrorHandler. + return errRetry + } + return nil } - return nil - } - p1.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { - if err == errRetry { - log.Println("retrying") - // Simulate calling the next backend. - p2.ServeHTTP(w, r) - return + first.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { + if err == errRetry { + log.Println("retrying") + + // Simulate calling the next backend. + // go run ./hack/successserver + next := newReverseProxy("http://localhost:8082") + next.ServeHTTP(w, newReq(r, body)) + return + } } - } - http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - p1.ServeHTTP(w, r) + log.Println("serving") + first.ServeHTTP(w, newReq(r, body)) })) } var errRetry = errors.New("retry") + +func newReq(r *http.Request, body []byte) *http.Request { + clone := r.Clone(r.Context()) + clone.Body = io.NopCloser(bytes.NewReader(body)) + return clone +} + +func newReverseProxy(addr string) *httputil.ReverseProxy { + u, err := url.Parse(addr) + if err != nil { + panic(err) + } + return httputil.NewSingleHostReverseProxy(u) +} diff --git a/hack/successserver/main.go b/hack/successserver/main.go index 2651dd95..2d656a9c 100644 --- a/hack/successserver/main.go +++ b/hack/successserver/main.go @@ -1,9 +1,14 @@ package main -import "net/http" +import ( + "io" + "net/http" + "os" +) func main() { http.ListenAndServe(":8082", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.Copy(os.Stdout, r.Body) w.Write([]byte("success\n")) })) }