Use Basepath over string concatenation

Basepath was previously not working here because the strings constructed
via concatenation had a trailing slash at the end:

Before:
  rootPath => "/someprefix/chronograf/v1/"

After:
  rootPath => "/someprefix/chronograf/v1"

The julienschmidt/httprouter that the bouk/httprouter is based on has
support for ignoring trailing slashes, which is behavior that we want.
However, routing decisions involving this rootPath string were being
made by a `strings.HasPrefix` function. This conditional seeks to
apply the token middleware only in cases where routes _under_
`/chronograf/v1` are accessed (e.g. `/chronograf/v1/sources`). In cases
where the paths were effectively equal, this conditional accidentally
worked because the string `/chronograf/v1` does not have the prefix
`/chronograf/v1/`. When this was corrected to use `path.Join`, this case
became true and caused the token middleware to be applied.

`path.Join` is the correct way to construct paths, since this prevents
issues where a fragment like `/foo/` is concatenated with a fragment
like `/bar/quux/` to yield the string `/foo//bar/quux/`.

Given that continuing to use concatenation is no longer an option, the
solution is to compare the lengths of the strings to ensure that the
path under comparison is longer than the prefix it's being tested
against. This guarantees that the subject path is a route underneath the
`/chronograf/v1` route.
pull/10616/head
Tim Raymond 2017-05-04 11:37:07 -04:00
parent 93acebffc6
commit 0141f0870c
1 changed files with 3 additions and 6 deletions

View File

@ -234,16 +234,13 @@ func AuthAPI(opts MuxOpts, router chronograf.Router) (http.Handler, AuthRoutes)
})
}
// Y U NO WORKY WITH PATH JOIN?
//rootPath := path.Join(opts.Basepath, "/chronograf/v1/")
//logoutPath := path.Join(opts.Basepath, "/oauth/logout")
rootPath := opts.Basepath + "/chronograf/v1/"
logoutPath := opts.Basepath + "/oauth/logout"
rootPath := path.Join(opts.Basepath, "/chronograf/v1/")
logoutPath := path.Join(opts.Basepath, "/oauth/logout")
tokenMiddleware := AuthorizedToken(opts.Auth, opts.Logger, router)
// Wrap the API with token validation middleware.
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, rootPath) || r.URL.Path == logoutPath {
if (strings.HasPrefix(r.URL.Path, rootPath) && len(r.URL.Path) > len(rootPath)) || r.URL.Path == logoutPath {
tokenMiddleware.ServeHTTP(w, r)
return
}