HTTP API: Don't loop redirecting when URL wasn't found 29/182229/2
authorMaciej Wereski <m.wereski@partner.samsung.com>
Thu, 21 Jun 2018 10:38:50 +0000 (12:38 +0200)
committerMaciej Wereski <m.wereski@partner.samsung.com>
Wed, 27 Jun 2018 15:49:38 +0000 (17:49 +0200)
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 <m.wereski@partner.samsung.com>
http/server/api/api.go
http/server/api/api_test.go

index cddbca0..2b443fb 100644 (file)
@@ -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)
        }
 }
 
index 94b89e2..f13661e 100644 (file)
@@ -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)
 }