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..cc2eb325 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,64 @@ 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(body, 0).ServeHTTP(w, newRequest(r, body)) + })) + +} + +var errRetry = errors.New("retry") + +func backend(body []byte, attempt int) http.Handler { + // go run ./hack/failserver + u, err := url.Parse(getEndpoint(attempt)) + if err != nil { + panic(err) + } + proxy := httputil.NewSingleHostReverseProxy(u) - 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(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 getEndpoint(attempt int) string { + switch attempt { + case 0: + return "http://localhost:8081" + default: + return "http://localhost:8082" + } +} -func newReq(r *http.Request, body []byte) *http.Request { +func newRequest(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) -}