diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 384abbee04f182275d7ef01e002123c55dc622aa..c0115f2c826b9ab1fba339b9cfa0b1a51495cbd8 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -196,3 +196,24 @@ func (h *HTTPBin) ResponseHeaders(w http.ResponseWriter, r *http.Request) { } w.Write(body) } + +// RelativeRedirect responds with an HTTP 302 redirect a given number of times +func (h *HTTPBin) RelativeRedirect(w http.ResponseWriter, r *http.Request) { + parts := strings.Split(r.URL.Path, "/") + if len(parts) != 3 { + http.Error(w, "Not found", http.StatusNotFound) + return + } + n, err := strconv.Atoi(parts[2]) + if err != nil || n < 1 { + http.Error(w, "Invalid redirect", http.StatusBadRequest) + } + + location := fmt.Sprintf("/relative-redirect/%d", n-1) + if n == 1 { + location = "/get" + } + + w.Header().Set("Location", location) + w.WriteHeader(http.StatusFound) +} diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index 7545812b3c330cabf9d32f00073260cd75f8862c..970ba8d031850bd36fd17805dd583809cf4ebad2 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -532,3 +532,42 @@ func TestResponseHeaders(t *testing.T) { } } } + +func TestRelativeRedirect__OK(t *testing.T) { + var tests = []struct { + n int + location string + }{ + {1, "/get"}, + {2, "/relative-redirect/1"}, + {100, "/relative-redirect/99"}, + } + + for _, test := range tests { + r, _ := http.NewRequest("GET", fmt.Sprintf("/relative-redirect/%d", test.n), nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, http.StatusFound) + assertHeader(t, w, "Location", test.location) + } +} + +func TestRelativeRedirect__Errors(t *testing.T) { + var tests = []struct { + given interface{} + status int + }{ + {3.14, http.StatusBadRequest}, + {-1, http.StatusBadRequest}, + {"foo", http.StatusBadRequest}, + } + + for _, test := range tests { + r, _ := http.NewRequest("GET", fmt.Sprintf("/relative-redirect/%v", test.given), nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, test.status) + } +} diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index 48e721430d608ebffcda583e2b26ed7c87a0f08b..531e616d5b2d4780f72f4e1399f1ba0fc33a61a8 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -67,6 +67,8 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/status/", h.Status) mux.HandleFunc("/response-headers", h.ResponseHeaders) + mux.HandleFunc("/relative-redirect/", h.RelativeRedirect) + return logger(cors(mux)) }