diff --git a/hack/failonceserver/main.go b/hack/failonceserver/main.go index e45588de..ca7437a3 100644 --- a/hack/failonceserver/main.go +++ b/hack/failonceserver/main.go @@ -1,7 +1,9 @@ package main import ( + "io" "net/http" + "os" "sync" ) @@ -10,7 +12,9 @@ func main() { var mtx sync.RWMutex paths := map[string]bool{} - http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.ListenAndServe(":8082", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.Copy(os.Stdout, r.Body) + mtx.RLock() shouldSucceed := paths[r.URL.Path] mtx.RUnlock() diff --git a/hack/retryproxy/main.go b/hack/retryproxy/main.go index 64534549..c24f6f78 100644 --- a/hack/retryproxy/main.go +++ b/hack/retryproxy/main.go @@ -3,6 +3,7 @@ package main import ( "bytes" "errors" + "fmt" "io" "log" "net/http" @@ -12,52 +13,68 @@ import ( func main() { http.ListenAndServe(":8080", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log.Println("serving") + body, err := io.ReadAll(r.Body) if err != nil { panic(err) } r.Body.Close() - // go run ./hack/failserver - first := newReverseProxy("http://localhost:8081") + fmt.Println("body:", string(body)) + + backend(r, body, 0).ServeHTTP(w, newRequest(r, body)) + })) + +} + +var errRetry = errors.New("retry") + +func backend(r *http.Request, body []byte, attempt int) http.Handler { + // go run ./hack/failserver + proxy := newReverseProxy(getEndpoint(attempt)) - first.ModifyResponse = func(r *http.Response) error { - if r.StatusCode == http.StatusServiceUnavailable { - // Returning an error will trigger the ErrorHandler. - return errRetry - } - return nil + proxy.ModifyResponse = func(r *http.Response) error { + if r.StatusCode == http.StatusServiceUnavailable { + // Returning an error will trigger the ErrorHandler. + return errRetry } + return nil + } - first.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { - if err == errRetry { - log.Println("retrying") + proxy.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 - } + // Simulate calling the next backend. + // go run ./hack/successserver + backend(r, body, attempt+1).ServeHTTP(w, newRequest(r, body)) + return } + } - log.Println("serving") - first.ServeHTTP(w, newReq(r, body)) - })) + return proxy } -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 getEndpoint(attempt int) string { + switch attempt { + case 0: + return "http://localhost:8081" + default: + return "http://localhost:8082" + } } -func newReverseProxy(addr string) *httputil.ReverseProxy { - u, err := url.Parse(addr) +func newReverseProxy(host string) *httputil.ReverseProxy { + u, err := url.Parse(host) if err != nil { panic(err) } return httputil.NewSingleHostReverseProxy(u) } + +func newRequest(r *http.Request, body []byte) *http.Request { + clone := r.Clone(r.Context()) + clone.Body = io.NopCloser(bytes.NewReader(body)) + return clone +}