From 38b908b90578606c119cd8e51d3336b59a0947dd Mon Sep 17 00:00:00 2001 From: Maciej Wereski Date: Thu, 21 Jun 2018 12:38:50 +0200 Subject: [PATCH] HTTP API: Don't loop redirecting when URL wasn't found Currently when api version isn't provided in URL then request is redirected to default one. If requested resource isn't found there then the redirected will be served by the same handler, so it will be redirected which results in another redirection and so on. This change introduces new handler that responds with 404 error when page wasn't found in default version of API. Change-Id: I1b67f7166d3b0d92500ab2f5727c2827b485d940 Signed-off-by: Maciej Wereski --- http/server/api/api.go | 17 +++++++++++++++++ http/server/api/api_test.go | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/http/server/api/api.go b/http/server/api/api.go index cddbca0..2b443fb 100644 --- a/http/server/api/api.go +++ b/http/server/api/api.go @@ -18,6 +18,7 @@ package api import ( + "encoding/json" "fmt" "net/http" @@ -66,6 +67,20 @@ func redirectToDefault(w http.ResponseWriter, r *http.Request, http.Redirect(w, r, u.String(), http.StatusPermanentRedirect) } +// setNotFoundHandler catches all requests that were redirected to default API, +// and not found there. +func notFoundHandler(w http.ResponseWriter, r *http.Request, _ map[string]string) { + srvErr := util.NewServerError(NotFoundError(r.URL.Path)) + data, err := json.Marshal(srvErr) + if err != nil { + data = []byte(srvErr.Err) + } else { + w.Header().Set("Content-Type", "application/json") + } + w.WriteHeader(srvErr.Status) + w.Write(data) +} + // setDefaultAPI register handler for API calls that lack API version in path. func setDefaultAPIRedirect(prefix *httptreemux.Group) { for _, method := range [...]string{ @@ -80,6 +95,8 @@ func setDefaultAPIRedirect(prefix *httptreemux.Group) { http.MethodTrace, } { prefix.Handle(method, "/*path", redirectToDefault) + // Redirect was done, requested API call wasn't found. + prefix.Handle(method, "/"+defaultAPI+"/*path", notFoundHandler) } } diff --git a/http/server/api/api_test.go b/http/server/api/api_test.go index 94b89e2..f13661e 100644 --- a/http/server/api/api_test.go +++ b/http/server/api/api_test.go @@ -17,6 +17,7 @@ package api import ( + "encoding/json" "errors" "flag" "io/ioutil" @@ -26,6 +27,7 @@ import ( "path/filepath" "testing" + . "git.tizen.org/tools/boruta" util "git.tizen.org/tools/boruta/http" "git.tizen.org/tools/boruta/matcher" "git.tizen.org/tools/boruta/requests" @@ -143,4 +145,16 @@ func TestRedirectToDefault(t *testing.T) { // Response is checked in redirCheck. _, err := client.Post(srv.URL+reqPath, "text/plain", nil) assert.Nil(err) + + // Path to default version of API, which wasn't found. + badPath := "/api/" + defaultAPI + "/missing/test" + var srvErr util.ServerError + resp, err := client.Post(srv.URL+badPath, "text/plain", nil) + assert.Nil(err) + defer resp.Body.Close() + decoder := json.NewDecoder(resp.Body) + assert.Equal("application/json", resp.Header.Get("Content-Type")) + err = decoder.Decode(&srvErr) + assert.Equal(http.StatusNotFound, resp.StatusCode) + assert.Equal(NotFoundError(badPath).Error(), srvErr.Err) } -- 2.7.4