From 8486766a604ec0550abea030c2c39f31a74bf5d4 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 6 Apr 2016 13:06:31 +0200 Subject: [PATCH 1/5] Add multiple rules Signed-off-by: Emile Vauge --- middlewares/stripPrefix.go | 17 ++++---- rules.go | 82 +++++++++++++++++++++++++++++--------- server.go | 10 ++--- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/middlewares/stripPrefix.go b/middlewares/stripPrefix.go index 92eb7a5f1..175e29502 100644 --- a/middlewares/stripPrefix.go +++ b/middlewares/stripPrefix.go @@ -7,18 +7,19 @@ import ( // StripPrefix is a middleware used to strip prefix from an URL request type StripPrefix struct { - Handler http.Handler - Prefix string + Handler http.Handler + Prefixes []string } func (s *StripPrefix) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if p := strings.TrimPrefix(r.URL.Path, s.Prefix); len(p) < len(r.URL.Path) { - r.URL.Path = p - r.RequestURI = r.URL.RequestURI() - s.Handler.ServeHTTP(w, r) - } else { - http.NotFound(w, r) + for _, prefix := range s.Prefixes { + if p := strings.TrimPrefix(r.URL.Path, strings.TrimSpace(prefix)); len(p) < len(r.URL.Path) { + r.URL.Path = p + r.RequestURI = r.URL.RequestURI() + s.Handler.ServeHTTP(w, r) + } } + http.NotFound(w, r) } // SetHandler sets handler diff --git a/rules.go b/rules.go index 8d43a884c..29152008a 100644 --- a/rules.go +++ b/rules.go @@ -3,7 +3,9 @@ package main import ( "errors" "github.com/gorilla/mux" + "net/http" "reflect" + "sort" "strings" ) @@ -12,26 +14,65 @@ type Rules struct { route *serverRoute } -func (r *Rules) host(host string) *mux.Route { - return r.route.route.Host(host) +func (r *Rules) host(hosts ...string) *mux.Route { + return r.route.route.MatcherFunc(func(req *http.Request, route *mux.RouteMatch) bool { + for _, host := range hosts { + if strings.EqualFold(req.Host, strings.TrimSpace(host)) { + return true + } + } + return false + }) } -func (r *Rules) path(path string) *mux.Route { - return r.route.route.Path(path) +func (r *Rules) hostRegexp(hosts ...string) *mux.Route { + router := r.route.route.Subrouter() + for _, host := range hosts { + router.Host(strings.TrimSpace(host)) + } + return r.route.route } -func (r *Rules) pathPrefix(path string) *mux.Route { - return r.route.route.PathPrefix(path) +func (r *Rules) path(paths ...string) *mux.Route { + router := r.route.route.Subrouter() + for _, path := range paths { + router.Path(strings.TrimSpace(path)) + } + return r.route.route } -func (r *Rules) pathStrip(path string) *mux.Route { - r.route.stripPrefix = path - return r.route.route.Path(path) +func (r *Rules) pathPrefix(paths ...string) *mux.Route { + router := r.route.route.Subrouter() + for _, path := range paths { + router.PathPrefix(strings.TrimSpace(path)) + } + return r.route.route } -func (r *Rules) pathPrefixStrip(path string) *mux.Route { - r.route.stripPrefix = path - return r.route.route.PathPrefix(path) +type bySize []string + +func (a bySize) Len() int { return len(a) } +func (a bySize) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a bySize) Less(i, j int) bool { return len(a[i]) > len(a[j]) } + +func (r *Rules) pathStrip(paths ...string) *mux.Route { + sort.Sort(bySize(paths)) + r.route.stripPrefixes = paths + router := r.route.route.Subrouter() + for _, path := range paths { + router.Path(strings.TrimSpace(path)) + } + return r.route.route +} + +func (r *Rules) pathPrefixStrip(paths ...string) *mux.Route { + sort.Sort(bySize(paths)) + r.route.stripPrefixes = paths + router := r.route.route.Subrouter() + for _, path := range paths { + router.PathPrefix(strings.TrimSpace(path)) + } + return r.route.route } func (r *Rules) methods(methods ...string) *mux.Route { @@ -50,32 +91,33 @@ func (r *Rules) headersRegexp(headers ...string) *mux.Route { func (r *Rules) Parse(expression string) (*mux.Route, error) { functions := map[string]interface{}{ "Host": r.host, + "HostRegexp": r.hostRegexp, "Path": r.path, "PathStrip": r.pathStrip, "PathPrefix": r.pathPrefix, "PathPrefixStrip": r.pathPrefixStrip, - "Methods": r.methods, + "Method": r.methods, "Headers": r.headers, "HeadersRegexp": r.headersRegexp, } f := func(c rune) bool { - return c == ':' || c == '=' + return c == ':' } // get function parsedFunctions := strings.FieldsFunc(expression, f) - if len(parsedFunctions) != 2 { + if len(parsedFunctions) == 0 { return nil, errors.New("Error parsing rule: " + expression) } parsedFunction, ok := functions[parsedFunctions[0]] if !ok { return nil, errors.New("Error parsing rule: " + expression + ". Unknow function: " + parsedFunctions[0]) } - + parsedFunctions = append(parsedFunctions[:0], parsedFunctions[1:]...) fargs := func(c rune) bool { return c == ',' || c == ';' } // get function - parsedArgs := strings.FieldsFunc(parsedFunctions[1], fargs) + parsedArgs := strings.FieldsFunc(strings.Join(parsedFunctions, ":"), fargs) if len(parsedArgs) == 0 { return nil, errors.New("Error parsing args from rule: " + expression) } @@ -86,7 +128,11 @@ func (r *Rules) Parse(expression string) (*mux.Route, error) { } method := reflect.ValueOf(parsedFunction) if method.IsValid() { - return method.Call(inputs)[0].Interface().(*mux.Route), nil + resultRoute := method.Call(inputs)[0].Interface().(*mux.Route) + if resultRoute.GetError() != nil { + return nil, resultRoute.GetError() + } + return resultRoute, nil } return nil, errors.New("Method not found: " + parsedFunctions[0]) } diff --git a/server.go b/server.go index 820968ff3..f2e9e50ab 100644 --- a/server.go +++ b/server.go @@ -57,8 +57,8 @@ type serverEntryPoint struct { } type serverRoute struct { - route *mux.Route - stripPrefix string + route *mux.Route + stripPrefixes []string } // NewServer returns an initialized Server. @@ -471,10 +471,10 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo func (server *Server) wireFrontendBackend(serverRoute *serverRoute, handler http.Handler) { // strip prefix - if len(serverRoute.stripPrefix) > 0 { + if len(serverRoute.stripPrefixes) > 0 { serverRoute.route.Handler(&middlewares.StripPrefix{ - Prefix: serverRoute.stripPrefix, - Handler: handler, + Prefixes: serverRoute.stripPrefixes, + Handler: handler, }) } else { serverRoute.route.Handler(handler) From e36433c23adb771620e5e2c3a1d66be2a192bfd7 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 6 Apr 2016 14:07:51 +0200 Subject: [PATCH 2/5] Fix retry attempts Signed-off-by: Emile Vauge --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index f2e9e50ab..c9dbbc551 100644 --- a/server.go +++ b/server.go @@ -425,7 +425,7 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo } // retry ? if globalConfiguration.Retry != nil { - retries := len(configuration.Backends[frontend.Backend].Servers) - 1 + retries := len(configuration.Backends[frontend.Backend].Servers) if globalConfiguration.Retry.Attempts > 0 { retries = globalConfiguration.Retry.Attempts } From 4d2c85ffdcb6cc71fa51460b3d72f8080234cd29 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 6 Apr 2016 14:30:29 +0200 Subject: [PATCH 3/5] Fix multiple response.WriteHeader calls Signed-off-by: Emile Vauge --- middlewares/stripPrefix.go | 1 + 1 file changed, 1 insertion(+) diff --git a/middlewares/stripPrefix.go b/middlewares/stripPrefix.go index 175e29502..2a13c78bb 100644 --- a/middlewares/stripPrefix.go +++ b/middlewares/stripPrefix.go @@ -17,6 +17,7 @@ func (s *StripPrefix) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.URL.Path = p r.RequestURI = r.URL.RequestURI() s.Handler.ServeHTTP(w, r) + return } } http.NotFound(w, r) From 30db47d9b67919f7594b64fc6e37208e41e56a22 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 6 Apr 2016 15:28:25 +0200 Subject: [PATCH 4/5] Fix SSH key, I hope... Signed-off-by: Emile Vauge --- .travis.yml | 11 +++-------- .travis/traefik.id_rsa.enc | Bin 3248 -> 3264 bytes script/deploy.sh | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 979ded43c..db7f46d8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,14 @@ branches: except: - /^v\d\.\d\.\d.*$/ - env: REPO: $TRAVIS_REPO_SLUG VERSION: v1.0.0-beta.$TRAVIS_BUILD_NUMBER - + global: + secure: btt4r13t09gQlHb6gYrvGC2yGCMMHfnp1Mz1RQedc4Mpf/FfT8aE6xmK2a2i9CCvskjrP0t/BFaS4yxIURjnFRn+ugQIEa0pLspB9UJArW/vgOSpIWM9/OQ/fg8z5XuMxN6Md4DL1/iLypMNSageA1x0TRdt89+D1N1dALpg5XRCXLFbC84TLi0gjlFuib9ibPKzEhLT+anCRJ6iZMzeupDSoaCVbAtJMoDvXw4+4AcRZ1+k4MybBLyCib5boaEOt4pTT88mz4Kk0YaMwPVJyg9Qv36VqyUcPS09Yd95LuyVQ4+tZt8Y1ccbIzULsK+sLM3hLCzxlmlpN3dQBlZJiiRtQde0mgGAKyC0P0A1XjuDTywcsa5edB+fTk1Dsewz9xZ9V0NmMz8t+UNZnaSsAPga9i86jULbXUUwMVSzVRc+Xgx02liB/8qI1xYC9FM6ilStt7rn7mF0k3KbiWhcptgeXjO6Lah9FjEKd5w4MXsdUSTi/86rQaLo+kj+XdaTrXCTulKHyRyQEUj+8V1w0oVz7pcGjePHd7y5oU9ByifVQy6sytuFBfRZvugM5bKHo+i0pcWvixrZS42DrzwxZJsspANOvqSe5ifVbvOkfUppQdCBIwptxV5N1b49XPKU3W/w34QJ8xGmKp3TFA7WwVCztriFHjPgiRpB3EG99Bg= sudo: required - services: - docker - install: - sudo service docker stop - sudo curl https://get.docker.com/builds/Linux/x86_64/docker-1.10.1 -o /usr/bin/docker @@ -18,16 +16,13 @@ install: - sudo service docker start - pip install --user mkdocs - pip install --user pymdown-extensions - before_script: - make validate - make binary - script: - make test-unit - make test-integration - make crossbinary - make image - after_success: -- make deploy \ No newline at end of file +- make deploy diff --git a/.travis/traefik.id_rsa.enc b/.travis/traefik.id_rsa.enc index f7edf637fb1824c9d12f5c572eaa87ba32de9814..1a1bb76c4100668a67fda1e905cd1ce293444fce 100644 GIT binary patch literal 3264 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 literal 3248 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 diff --git a/script/deploy.sh b/script/deploy.sh index 4bd811c12..7b5515ecb 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -10,7 +10,7 @@ fi # load ssh key echo "Loading key..." -openssl aes-256-cbc -K $encrypted_27087ae1f4db_key -iv $encrypted_27087ae1f4db_iv -in .travis/traefik.id_rsa.enc -out ~/.ssh/traefik.id_rsa -d +openssl aes-256-cbc -d -k "$pass" -in .travis/traefik.id_rsa.enc -out ~/.ssh/traefik.id_rsa eval "$(ssh-agent -s)" chmod 600 ~/.ssh/traefik.id_rsa ssh-add ~/.ssh/traefik.id_rsa From 85fcff4cf7f152b36b4f49f02bd190560c88cff5 Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Wed, 6 Apr 2016 15:48:19 +0200 Subject: [PATCH 5/5] Multiple rules docs Signed-off-by: Emile Vauge --- docs/basics.md | 21 +++++++++++---------- traefik.sample.toml | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/basics.md b/docs/basics.md index b7d44a17d..230f83909 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -59,13 +59,14 @@ Here is an example of entrypoints definition: A frontend is a set of rules that forwards the incoming traffic from an entrypoint to a backend. Frontends can be defined using the following rules: -- `Headers`: Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched. For example: `Content-Type, application/json` -- `HeadersRegexp`: Regular expressions can be used with headers as well. It accepts a sequence of key/value pairs, where the value has regex support. For example: `Content-Type, application/(text|json)` -- `Host`: Host adds a matcher for the URL host. It accepts a template with zero or more URL variables enclosed by `{}`. Variables can define an optional regexp pattern to be matched: `www.traefik.io`, `{subdomain:[a-z]+}.traefik.io` -- `Methods`: Methods adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched, e.g.: `GET`, `POST`, `PUT` -- `Path`: Path adds a matcher for the URL path. It accepts a template with zero or more URL variables enclosed by `{}`. The template must start with a `/`. For exemple `/products/` `/articles/{category}/{id:[0-9]+}` +- `Headers: Content-Type, application/json`: Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched. +- `HeadersRegexp: Content-Type, application/(text|json)`: Regular expressions can be used with headers as well. It accepts a sequence of key/value pairs, where the value has regex support. +- `Host: traefik.io, www.traefik.io`: Match request host with given host list. +- `HostRegexp: traefik.io, {subdomain:[a-z]+}.traefik.io`: Adds a matcher for the URL hosts. It accepts templates with zero or more URL variables enclosed by `{}`. Variables can define an optional regexp pattern to be matched. +- `Method: GET, POST, PUT`: Methods adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched. +- `Path: /products/, /articles/{category}/{id:[0-9]+}`: Path adds a matcher for the URL paths. It accepts templates with zero or more URL variables enclosed by `{}`. - `PathStrip`: Same as `Path` but strip the given prefix from the request URL's Path. -- `PathPrefix`: PathPrefix adds a matcher for the URL path prefix. This matches if the given template is a prefix of the full URL path. +- `PathPrefix`: PathPrefix adds a matcher for the URL path prefixes. This matches if the given template is a prefix of the full URL path. - `PathPrefixStrip`: Same as `PathPrefix` but strip the given prefix from the request URL's Path. You can optionally enable `passHostHeader` to forward client `Host` header to the backend. @@ -77,21 +78,21 @@ Here is an example of frontends definition: [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" + rule = "Host: test.localhost, test2.localhost" [frontends.frontend2] backend = "backend1" passHostHeader = true entrypoints = ["https"] # overrides defaultEntryPoints [frontends.frontend2.routes.test_1] - rule = "Host:{subdomain:[a-z]+}.localhost" + rule = "Host: localhost, {subdomain:[a-z]+}.localhost" [frontends.frontend3] backend = "backend2" rule = "Path:/test" ``` - Three frontends are defined: `frontend1`, `frontend2` and `frontend3` -- `frontend1` will forward the traffic to the `backend2` if the rule `Host:test.localhost` is matched -- `frontend2` will forward the traffic to the `backend1` if the rule `Host:{subdomain:[a-z]+}.localhost` is matched (forwarding client `Host` header to the backend) +- `frontend1` will forward the traffic to the `backend2` if the rule `Host: test.localhost, test2.localhost` is matched +- `frontend2` will forward the traffic to the `backend1` if the rule `Host: localhost, {subdomain:[a-z]+}.localhost` is matched (forwarding client `Host` header to the backend) - `frontend3` will forward the traffic to the `backend2` if the rule `Path:/test` is matched ## Backends diff --git a/traefik.sample.toml b/traefik.sample.toml index 945f963a3..6141d1ea0 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -513,7 +513,7 @@ # [frontends.frontend1] # backend = "backend2" # [frontends.frontend1.routes.test_1] -# rule = "Host:test.localhost" +# rule = "Host: test.localhost, other.localhost" # [frontends.frontend2] # backend = "backend1" # passHostHeader = true @@ -523,4 +523,4 @@ # [frontends.frontend3] # entrypoints = ["http", "https"] # overrides defaultEntryPoints # backend = "backend2" -# rule = "Path:/test" \ No newline at end of file +# rule = "Path: /test, /other" \ No newline at end of file