From 0b5fd397fd908d005b39d2d55e2e12581c937368 Mon Sep 17 00:00:00 2001 From: Will McCutchen <will@mccutch.org> Date: Fri, 14 Oct 2016 16:51:28 -0700 Subject: [PATCH] Add /redirect/:n handler --- httpbin/handlers.go | 10 +++++++ httpbin/handlers_test.go | 62 ++++++++++++++++++++++++++++++++++++++++ httpbin/httpbin.go | 1 + 3 files changed, 73 insertions(+) diff --git a/httpbin/handlers.go b/httpbin/handlers.go index a325101..eefc635 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -197,6 +197,7 @@ func redirectLocation(r *http.Request, relative bool, n int) string { } else { u := getURL(r) u.Path = path + u.RawQuery = "" location = u.String() } @@ -218,6 +219,15 @@ func doRedirect(w http.ResponseWriter, r *http.Request, relative bool) { w.WriteHeader(http.StatusFound) } +// Redirect responds with 302 redirect a given number of times. Defaults to a +// relative redirect, but an ?absolute=true query param will trigger an +// absolute redirect. +func (h *HTTPBin) Redirect(w http.ResponseWriter, r *http.Request) { + params := r.URL.Query() + relative := strings.ToLower(params.Get("absolute")) != "true" + doRedirect(w, r, relative) +} + // RelativeRedirect responds with an HTTP 302 redirect a given number of times func (h *HTTPBin) RelativeRedirect(w http.ResponseWriter, r *http.Request) { doRedirect(w, r, true) diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index 5dd6e94..601b764 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -728,6 +728,68 @@ func TestResponseHeaders__OverrideContentType(t *testing.T) { assertContentType(t, w, contentType) } +func TestRedirect__OK(t *testing.T) { + var tests = []struct { + relative bool + n int + location string + }{ + {true, 1, "/get"}, + {true, 2, "/relative-redirect/1"}, + {true, 100, "/relative-redirect/99"}, + + {false, 1, "http://host/get"}, + {false, 2, "http://host/absolute-redirect/1"}, + {false, 100, "http://host/absolute-redirect/99"}, + } + + for _, test := range tests { + u := fmt.Sprintf("/redirect/%d", test.n) + if !test.relative { + u = fmt.Sprintf("%s?absolute=true", u) + } + r, _ := http.NewRequest("GET", u, nil) + r.Host = "host" + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, http.StatusFound) + assertHeader(t, w, "Location", test.location) + } +} + +func TestRedirect__Errors(t *testing.T) { + var tests = []struct { + relative bool + given interface{} + status int + }{ + {true, 3.14, http.StatusBadRequest}, + {true, -1, http.StatusBadRequest}, + {true, "", http.StatusBadRequest}, + {true, "foo", http.StatusBadRequest}, + {true, "10/bar", http.StatusNotFound}, + + {false, 3.14, http.StatusBadRequest}, + {false, -1, http.StatusBadRequest}, + {false, "", http.StatusBadRequest}, + {false, "foo", http.StatusBadRequest}, + {false, "10/bar", http.StatusNotFound}, + } + + for _, test := range tests { + u := fmt.Sprintf("/redirect/%v", test.given) + if !test.relative { + u = fmt.Sprintf("%s?absolute=true", u) + } + r, _ := http.NewRequest("GET", u, nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, test.status) + } +} + func TestAbsoluteAndRelativeRedirects__OK(t *testing.T) { var tests = []struct { relative bool diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index 2dffdb4..35fca2f 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -67,6 +67,7 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/status/", h.Status) mux.HandleFunc("/response-headers", h.ResponseHeaders) + mux.HandleFunc("/redirect/", h.Redirect) mux.HandleFunc("/relative-redirect/", h.RelativeRedirect) mux.HandleFunc("/absolute-redirect/", h.AbsoluteRedirect) -- GitLab