Add keepTrailingSlash option

This commit is contained in:
SALLEYRON Julien 2018-10-17 14:22:03 +02:00 committed by Traefiker Bot
parent 70fa42aee0
commit 95d86d84b4
6 changed files with 100 additions and 2 deletions

View file

@ -87,6 +87,7 @@ type GlobalConfiguration struct {
RespondingTimeouts *RespondingTimeouts `description:"Timeouts for incoming requests to the Traefik instance" export:"true"`
ForwardingTimeouts *ForwardingTimeouts `description:"Timeouts for requests forwarded to the backend servers" export:"true"`
AllowMinWeightZero bool `description:"Allow weight to take 0 as minimum real value." export:"true"` // Deprecated
KeepTrailingSlash bool `description:"Do not remove trailing slash." export:"true"` // Deprecated
Web *WebCompatibility `description:"(Deprecated) Enable Web backend with default settings" export:"true"` // Deprecated
Docker *docker.Provider `description:"Enable Docker backend with default settings" export:"true"`
File *file.Provider `description:"Enable File backend with default settings" export:"true"`

View file

@ -33,6 +33,13 @@
#
# checkNewVersion = false
# Tells traefik whether it should keep the trailing slashes in the paths (e.g. /paths/) or redirect to the no trailing slash paths instead (/paths).
#
# Optional
# Default: false
#
# keepTrailingSlash = false
# Providers throttle duration.
#
# Optional
@ -103,6 +110,25 @@ If you encounter 'too many open files' errors, you can either increase this valu
- `defaultEntryPoints`: Entrypoints to be used by frontends that do not specify any entrypoint.
Each frontend can specify its own entrypoints.
- `keepTrailingSlash`: Tells Træfik whether it should keep the trailing slashes that might be present in the paths of incoming requests (true), or if it should redirect to the slashless version of the URL (default behavior: false)
!!! note
Beware that the value of `keepTrailingSlash` can have a significant impact on the way your frontend rules are interpreted.
The table below tries to sum up several behaviors depending on requests/configurations.
The current default behavior is deprecated and kept for compatibility reasons.
As a consequence, we encourage you to set `keepTrailingSlash` to true.
| Incoming request | keepTrailingSlash | Path:{value} | Behavior
|----------------------|-------------------|--------------|----------------------------|
| http://foo.com/path/ | false | Path:/path/ | Proceeds with the request |
| http://foo.com/path/ | false | Path:/path | 301 to http://foo.com/path |
| http://foo.com/path | false | Path:/path/ | Proceeds with the request |
| http://foo.com/path | false | Path:/path | Proceeds with the request |
| http://foo.com/path/ | true | Path:/path/ | Proceeds with the request |
| http://foo.com/path/ | true | Path:/path | 404 |
| http://foo.com/path | true | Path:/path/ | 404 |
| http://foo.com/path | true | Path:/path | Proceeds with the request |
## Constraints

View file

@ -396,3 +396,51 @@ func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) {
c.Assert(err, checker.IsNil)
}
func (s *SimpleSuite) TestDontKeepTrailingSlash(c *check.C) {
file := s.adaptFile(c, "fixtures/keep_trailing_slash.toml", struct {
KeepTrailingSlash bool
}{false})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
defer output(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
oldCheckRedirect := http.DefaultClient.CheckRedirect
http.DefaultClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
err = try.GetRequest("http://127.0.0.1:8000/test/foo/", 1*time.Second, try.StatusCodeIs(http.StatusMovedPermanently))
c.Assert(err, checker.IsNil)
http.DefaultClient.CheckRedirect = oldCheckRedirect
}
func (s *SimpleSuite) TestKeepTrailingSlash(c *check.C) {
file := s.adaptFile(c, "fixtures/keep_trailing_slash.toml", struct {
KeepTrailingSlash bool
}{true})
defer os.Remove(file)
cmd, output := s.traefikCmd(withConfigFile(file))
defer output(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
oldCheckRedirect := http.DefaultClient.CheckRedirect
http.DefaultClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
err = try.GetRequest("http://127.0.0.1:8000/test/foo/", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
http.DefaultClient.CheckRedirect = oldCheckRedirect
}

View file

@ -0,0 +1,23 @@
defaultEntryPoints = ["http"]
keepTrailingSlash = {{ .KeepTrailingSlash }}
[entryPoints]
[entryPoints.http]
address = ":8000"
logLevel = "DEBUG"
[file]
# rules
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://172.17.0.2:80"
weight = 1
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Path:/test/foo"

View file

@ -627,7 +627,7 @@ func buildProxyProtocolListener(entryPoint *configuration.EntryPoint, listener n
func (s *Server) buildInternalRouter(entryPointName string) *mux.Router {
internalMuxRouter := mux.NewRouter()
internalMuxRouter.StrictSlash(true)
internalMuxRouter.StrictSlash(!s.globalConfiguration.KeepTrailingSlash)
internalMuxRouter.SkipClean(true)
if entryPoint, ok := s.entryPoints[entryPointName]; ok && entryPoint.InternalRouter != nil {

View file

@ -633,7 +633,7 @@ func buildDefaultCertificate(defaultCertificate *traefiktls.Certificate) (*tls.C
func (s *Server) buildDefaultHTTPRouter() *mux.Router {
rt := mux.NewRouter()
rt.NotFoundHandler = s.wrapHTTPHandlerWithAccessLog(http.HandlerFunc(http.NotFound), "backend not found")
rt.StrictSlash(true)
rt.StrictSlash(!s.globalConfiguration.KeepTrailingSlash)
rt.SkipClean(true)
return rt
}