1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2024-11-28 09:08:44 +02:00

Redirect request if it would match with an appended trailing slash

This commit is contained in:
Joel Speed 2021-03-07 12:42:10 +00:00
parent 6c62b25bf1
commit 8a06779d41
No known key found for this signature in database
GPG Key ID: 6E80578D6751DEFB
3 changed files with 53 additions and 0 deletions

View File

@ -1,6 +1,7 @@
package upstream
import (
"context"
"fmt"
"net/http"
"net/url"
@ -50,6 +51,8 @@ func NewProxy(upstreams options.Upstreams, sigData *options.SignatureData, write
return nil, fmt.Errorf("unknown scheme for upstream %q: %q", upstream.ID, u.Scheme)
}
}
registerTrailingSlashHandler(m.serveMux)
return m, nil
}
@ -120,3 +123,25 @@ func (m *multiUpstreamProxy) registerRewriteHandler(upstream options.Upstream, h
return nil
}
// registerTrailingSlashHandler creates a new matcher that will check if the
// requested path would match if it had a trailing slash appended.
// If the path matches with a trailing slash, we send back a redirect.
// This allows us to be consistent with the built in go servemux implementation.
func registerTrailingSlashHandler(serveMux *mux.Router) {
serveMux.MatcherFunc(func(req *http.Request, _ *mux.RouteMatch) bool {
if strings.HasSuffix(req.URL.Path, "/") {
return false
}
// Use a separate RouteMatch so that we can redirect to the path + /.
// If we pass through the match then the matched backed will be served
// instead of the redirect handler.
m := &mux.RouteMatch{}
slashReq := req.Clone(context.Background())
slashReq.URL.Path += "/"
return serveMux.Match(slashReq, m)
}).Handler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
http.Redirect(rw, req, req.URL.String()+"/", http.StatusMovedPermanently)
}))
}

View File

@ -29,6 +29,7 @@ var _ = Describe("Proxy Suite", func() {
}
ok := http.StatusOK
accepted := http.StatusAccepted
upstreams := options.Upstreams{
{
@ -47,6 +48,12 @@ var _ = Describe("Proxy Suite", func() {
Static: true,
StaticCode: &ok,
},
{
ID: "static-backend-no-trailing-slash",
Path: "/static",
Static: true,
StaticCode: &accepted,
},
{
ID: "bad-http-backend",
Path: "/bad-http/",
@ -235,5 +242,25 @@ var _ = Describe("Proxy Suite", func() {
},
upstream: "backend-with-rewrite-prefix",
}),
Entry("with a request to a path, missing the trailing slash", &proxyTableInput{
target: "http://example.localhost/http",
response: testHTTPResponse{
code: 301,
header: map[string][]string{
contentType: {textHTMLUTF8},
"Location": {"http://example.localhost/http/"},
},
raw: "<a href=\"http://example.localhost/http/\">Moved Permanently</a>.\n\n",
},
}),
Entry("with a request to a path, missing the trailing slash, but registered separately", &proxyTableInput{
target: "http://example.localhost/static",
response: testHTTPResponse{
code: 202,
header: map[string][]string{},
raw: "Authenticated",
},
upstream: "static-backend-no-trailing-slash",
}),
)
})

View File

@ -59,6 +59,7 @@ const (
acceptEncoding = "Accept-Encoding"
applicationJSON = "application/json"
textPlainUTF8 = "text/plain; charset=utf-8"
textHTMLUTF8 = "text/html; charset=utf-8"
gapAuth = "Gap-Auth"
gapSignature = "Gap-Signature"
)