Add keepTrailingSlash option
This commit is contained in:
parent
70fa42aee0
commit
95d86d84b4
6 changed files with 100 additions and 2 deletions
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
23
integration/fixtures/keep_trailing_slash.toml
Normal file
23
integration/fixtures/keep_trailing_slash.toml
Normal 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"
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue