diff --git a/docs/index.md b/docs/index.md index 188104170..6ab689904 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,25 +2,25 @@ Træfɪk

-# Documentation +# Documentation - [Basics](#basics) -- [Launch configuration](#launch) -- [Global configuration](#global) -- [File backend](#file) -- [API backend](#api) -- [Docker backend](#docker) -- [Mesos/Marathon backend](#marathon) -- [Consul backend](#consul) -- [Consul catalog backend](#consulcatalog) -- [Etcd backend](#etcd) -- [Zookeeper backend](#zk) -- [Boltdb backend](#boltdb) -- [Atomic configuration changes](#atomicconfig) +- [Launch configuration](#launch-configuration) +- [Global configuration](#global-configuration) +- [File backend](#file-backend) +- [API backend](#api-backend) +- [Docker backend](#docker-backend) +- [Mesos/Marathon backend](#marathon-backend) +- [Consul backend](#consul-backend) +- [Consul catalog backend](#consul-catalog-backend) +- [Etcd backend](#etcd-backend) +- [Zookeeper backend](#zookeeper-backend) +- [Boltdb backend](#boltdb-backend) +- [Atomic configuration changes](#atomic-configuration-changes) - [Benchmarks](#benchmarks) -## Basics +## Basics Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. @@ -28,12 +28,12 @@ It supports several backends ([Docker :whale:](https://www.docker.com/), [Mesos/ Basically, Træfɪk is a http router, which sends traffic from frontends to http backends, following rules you have configured. -### Frontends +### Frontends 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: `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: `application/(text|json)` +- `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]+}` @@ -70,7 +70,7 @@ For example: - `ResponseCodeRatio(500, 600, 0, 600) > 0.5`: ratio of response codes in range [500-600) to [0-600) -## Launch configuration +## Launch configuration Træfɪk can be configured using a TOML file configuration, arguments, or both. By default, Træfɪk will try to find a `traefik.toml` in the following places: @@ -176,7 +176,7 @@ Flags: Use "traefik [command] --help" for more information about a command. ``` -## Global configuration +## Global configuration ```toml # traefik.toml @@ -432,24 +432,21 @@ entryPoint = "https" [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] - rule = "Host" - value = "test.localhost" + rule = "Host:test.localhost" [frontends.frontend2] backend = "backend1" passHostHeader = true entrypoints = ["https"] # overrides defaultEntryPoints [frontends.frontend2.routes.test_1] - rule = "Host" - value = "{subdomain:[a-z]+}.localhost" + rule = "Host:{subdomain:[a-z]+}.localhost" [frontends.frontend3] entrypoints = ["http", "https"] # overrides defaultEntryPoints backend = "backend2" - rule = "Path" - value = "/test" + rule = "Path:/test" ``` -## File backend +## File backend Like any other reverse proxy, Træfɪk can be configured with a file. You have two choices: @@ -502,20 +499,17 @@ logLevel = "DEBUG" [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] - rule = "Host" - value = "test.localhost" + rule = "Host:test.localhost" [frontends.frontend2] backend = "backend1" passHostHeader = true entrypoints = ["https"] # overrides defaultEntryPoints [frontends.frontend2.routes.test_1] - rule = "Host" - value = "{subdomain:[a-z]+}.localhost" + rule = "Host:{subdomain:[a-z]+}.localhost" [frontends.frontend3] entrypoints = ["http", "https"] # overrides defaultEntryPoints backend = "backend2" - rule = "Path" - value = "/test" + rule = "Path:/test" ``` - or put your rules in a separate file, for example `rules.tml`: @@ -569,20 +563,17 @@ filename = "rules.toml" [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] - rule = "Host" - value = "test.localhost" + rule = "Host:test.localhost" [frontends.frontend2] backend = "backend1" passHostHeader = true entrypoints = ["https"] # overrides defaultEntryPoints [frontends.frontend2.routes.test_1] - rule = "Host" - value = "{subdomain:[a-z]+}.localhost" + rule = "Host:{subdomain:[a-z]+}.localhost" [frontends.frontend3] entrypoints = ["http", "https"] # overrides defaultEntryPoints backend = "backend2" - rule = "Path" - value = "/test" + rule = "Path:/test" ``` If you want Træfɪk to watch file changes automatically, just add: @@ -592,7 +583,7 @@ If you want Træfɪk to watch file changes automatically, just add: watch = true ``` -## API backend +## API backend Træfik can be configured using a restful api. To enable it: @@ -669,8 +660,7 @@ $ curl -s "http://localhost:8080/api" | jq . "frontend2": { "routes": { "test_2": { - "value": "/test", - "rule": "Path" + "rule": "Path:/test" } }, "backend": "backend1" @@ -678,8 +668,7 @@ $ curl -s "http://localhost:8080/api" | jq . "frontend1": { "routes": { "test_1": { - "value": "test.localhost", - "rule": "Host" + "rule": "Host:test.localhost" } }, "backend": "backend2" @@ -736,7 +725,7 @@ $ curl -s "http://localhost:8080/api" | jq . - `/api/providers/{provider}/frontends/{frontend}/routes/{route}`: `GET` a route in a frontend -## Docker backend +## Docker backend Træfɪk can be configured to use Docker as a backend configuration: @@ -792,14 +781,13 @@ Labels can be used on containers to override default behaviour: - `traefik.protocol=https`: override the default `http` protocol - `traefik.weight=10`: assign this weight to the container - `traefik.enable=false`: disable this container in Træfɪk -- `traefik.frontend.rule=Host`: override the default frontend rule (Default: Host). See [frontends](#frontends). -- `traefik.frontend.value=test.example.com`: override the default frontend value (Default: `{containerName}.{domain}`) See [frontends](#frontends). Must be associated with label traefik.frontend.rule. +- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. * `traefik.domain=traefik.localhost`: override the default domain -## Marathon backend +## Marathon backend Træfɪk can be configured to use Marathon as a backend configuration: @@ -873,13 +861,12 @@ Labels can be used on containers to override default behaviour: - `traefik.protocol=https`: override the default `http` protocol - `traefik.weight=10`: assign this weight to the application - `traefik.enable=false`: disable this application in Træfɪk -- `traefik.frontend.rule=Host`: override the default frontend rule (Default: Host). See [frontends](#frontends). -- `traefik.frontend.value=test.example.com`: override the default frontend value (Default: `{appName}.{domain}`) See [frontends](#frontends). Must be associated with label traefik.frontend.rule. +- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. * `traefik.domain=traefik.localhost`: override the default domain -## Consul backend +## Consul backend Træfɪk can be configured to use Consul as a backend configuration: @@ -929,48 +916,41 @@ prefix = "traefik" # insecureskipverify = true ``` -The Keys-Values structure should look (using `prefix = "/traefik"`): +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. -- backend 1 +## Consul catalog backend -| Key | Value | -|--------------------------------------------------------|-----------------------------| -| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | -| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik/backends/backend1/servers/server1/weight` | `10` | -| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | -| `/traefik/backends/backend1/servers/server2/weight` | `1` | +Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration: -- backend 2 +```toml +################################################################ +# Consul Catalog configuration backend +################################################################ -| Key | Value | -|-----------------------------------------------------|------------------------| -| `/traefik/backends/backend2/loadbalancer/method` | `drr` | -| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | -| `/traefik/backends/backend2/servers/server1/weight` | `1` | -| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | -| `/traefik/backends/backend2/servers/server2/weight` | `2` | +# Enable Consul Catalog configuration backend +# +# Optional +# +[consulCatalog] -- frontend 1 +# Consul server endpoint +# +# Required +# +endpoint = "127.0.0.1:8500" -| Key | Value | -|----------------------------------------------------|------------------| -| `/traefik/frontends/frontend1/backend` | `backend2` | -| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host` | -| `/traefik/frontends/frontend1/routes/test_1/value` | `test.localhost` | +# Default domain used. +# +# Optional +# +domain = "consul.localhost" +``` -- frontend 2 - -| Key | Value | -|----------------------------------------------------|------------| -| `/traefik/frontends/frontend2/backend` | `backend1` | -| `/traefik/frontends/frontend2/passHostHeader` | `true` | -| `/traefik/frontends/frontend2/entrypoints` |`http,https`| -| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path` | -| `/traefik/frontends/frontend2/routes/test_2/value` | `/test` | +This backend will create routes matching on hostname based on the service name +used in consul. -## Etcd backend +## Etcd backend Træfɪk can be configured to use Etcd as a backend configuration: @@ -1020,79 +1000,10 @@ Træfɪk can be configured to use Etcd as a backend configuration: # insecureskipverify = true ``` -The Keys-Values structure should look (using `prefix = "/traefik"`): - -- backend 1 - -| Key | Value | -|--------------------------------------------------------|-----------------------------| -| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | -| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik/backends/backend1/servers/server1/weight` | `10` | -| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | -| `/traefik/backends/backend1/servers/server2/weight` | `1` | - -- backend 2 - -| Key | Value | -|-----------------------------------------------------|------------------------| -| `/traefik/backends/backend2/loadbalancer/method` | `drr` | -| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | -| `/traefik/backends/backend2/servers/server1/weight` | `1` | -| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | -| `/traefik/backends/backend2/servers/server2/weight` | `2` | - -- frontend 1 - -| Key | Value | -|----------------------------------------------------|------------------| -| `/traefik/frontends/frontend1/backend` | `backend2` | -| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host` | -| `/traefik/frontends/frontend1/routes/test_1/value` | `test.localhost` | - -- frontend 2 - -| Key | Value | -|----------------------------------------------------|------------| -| `/traefik/frontends/frontend2/backend` | `backend1` | -| `/traefik/frontends/frontend2/passHostHeader` | `true` | -| `/traefik/frontends/frontend2/entrypoints` |`http,https`| -| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path` | -| `/traefik/frontends/frontend2/routes/test_2/value` | `/test` | +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. -## Consul catalog backend - -Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration: - -```toml -################################################################ -# Consul Catalog configuration backend -################################################################ - -# Enable Consul Catalog configuration backend -# -# Optional -# -[consulCatalog] - -# Consul server endpoint -# -# Required -# -endpoint = "127.0.0.1:8500" - -# Default domain used. -# -# Optional -# -domain = "consul.localhost" -``` - -This backend will create routes matching on hostname based on the service name -used in consul. - -## Zookeeper backend +## Zookeeper backend Træfɪk can be configured to use Zookeeper as a backend configuration: @@ -1131,48 +1042,10 @@ Træfɪk can be configured to use Zookeeper as a backend configuration: # # filename = "zookeeper.tmpl" ``` -The Keys-Values structure should look (using `prefix = "/traefik"`): -- backend 1 +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. -| Key | Value | -|--------------------------------------------------------|-----------------------------| -| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | -| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik/backends/backend1/servers/server1/weight` | `10` | -| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | -| `/traefik/backends/backend1/servers/server2/weight` | `1` | - -- backend 2 - -| Key | Value | -|-----------------------------------------------------|------------------------| -| `/traefik/backends/backend2/loadbalancer/method` | `drr` | -| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | -| `/traefik/backends/backend2/servers/server1/weight` | `1` | -| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | -| `/traefik/backends/backend2/servers/server2/weight` | `2` | - -- frontend 1 - -| Key | Value | -|---------------------------------------------------|------------------| -| `/traefik/frontends/frontend1/backend | `backend2` | -| `/traefik/frontends/frontend1/routes/test_1/rule | `Host` | -| `/traefik/frontends/frontend1/routes/test_1/value | `test.localhost` | - -- frontend 2 - -| Key | Value | -|----------------------------------------------------|------------| -| `/traefik/frontends/frontend2/backend` | `backend1` | -| `/traefik/frontends/frontend2/passHostHeader` | `true` | -| `/traefik/frontends/frontend2/entrypoints` |`http,https`| -| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path` | -| `/traefik/frontends/frontend2/routes/test_2/value` | `/test` | - - -## BoltDB backend +## BoltDB backend Træfɪk can be configured to use BoltDB as a backend configuration: @@ -1212,7 +1085,49 @@ Træfɪk can be configured to use BoltDB as a backend configuration: # filename = "boltdb.tmpl" ``` -## Atomic configuration changes +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. + +## Key-value storage structure + +The Keys-Values structure should look (using `prefix = "/traefik"`): + +- backend 1 + +| Key | Value | +|--------------------------------------------------------|-----------------------------| +| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | +| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik/backends/backend1/servers/server1/weight` | `10` | +| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | +| `/traefik/backends/backend1/servers/server2/weight` | `1` | + +- backend 2 + +| Key | Value | +|-----------------------------------------------------|------------------------| +| `/traefik/backends/backend2/loadbalancer/method` | `drr` | +| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | +| `/traefik/backends/backend2/servers/server1/weight` | `1` | +| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | +| `/traefik/backends/backend2/servers/server2/weight` | `2` | + +- frontend 1 + +| Key | Value | +|---------------------------------------------------|-----------------------| +| `/traefik/frontends/frontend1/backend` | `backend2` | +| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host:test.localhost` | + +- frontend 2 + +| Key | Value | +|----------------------------------------------------|--------------| +| `/traefik/frontends/frontend2/backend` | `backend1` | +| `/traefik/frontends/frontend2/passHostHeader` | `true` | +| `/traefik/frontends/frontend2/entrypoints` | `http,https` | +| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path:/test` | + +## Atomic configuration changes The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix. @@ -1251,7 +1166,7 @@ Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` co Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik` prefix. Further, if the `/traefik/alias` key is set, all other sibling keys with the `/traefik` prefix are ignored. -## Benchmarks +## Benchmarks Here are some early Benchmarks between Nginx, HA-Proxy and Træfɪk acting as simple load balancers between two servers. diff --git a/glide.lock b/glide.lock index 07939a6a6..22a3d782f 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 21d4e8dc80c87101568a719ecf01d1af9a1b58f03c5c9dc864a8cb1005ddc160 -updated: 2016-03-29T21:50:20.577439177+02:00 +hash: a8cca3f2e5bde6b96d0c195402b14606877bc8630cd7f2f06e65e0884c6a008b +updated: 2016-03-29T23:24:08.772606184+02:00 imports: - name: github.com/alecthomas/template version: b867cc6ab45cece8143cfcc6fc9c77cf3f2c23c0 @@ -264,7 +264,7 @@ imports: subpackages: - bson - name: gopkg.in/square/go-jose.v1 - version: 7d9df93c5ee8a09ed250b3b2360972fa29b4bb3c + version: 40d457b439244b546f023d056628e5184136899b subpackages: - cipher - json diff --git a/glide.yaml b/glide.yaml index 77db5e230..40d65a62e 100644 --- a/glide.yaml +++ b/glide.yaml @@ -44,7 +44,7 @@ import: ref: 6b4e7dc5e3143b85ea77909c72caf89416fc2915 - package: github.com/gambol99/go-marathon ref: ade11d1dc2884ee1f387078fc28509559b6235d1 - - package: github.com/mailgun/predicate + - package: github.com/vulcand/predicate ref: cb0bff91a7ab7cf7571e661ff883fc997bc554a3 - package: github.com/thoas/stats ref: 54ed61c2b47e263ae2f01b86837b0c4bd1da28e8 diff --git a/integration/docker_test.go b/integration/docker_test.go index 5293dbb4a..f06406acb 100644 --- a/integration/docker_test.go +++ b/integration/docker_test.go @@ -133,8 +133,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels(c *check.C) { defer os.Remove(file) // Start a container with some labels labels := map[string]string{ - "traefik.frontend.rule": "Host", - "traefik.frontend.value": "my.super.host", + "traefik.frontend.rule": "Host:my.super.host", } s.startContainerWithLabels(c, "swarm:1.0.0", labels, "manage", "token://blabla") diff --git a/integration/fixtures/file/simple.toml b/integration/fixtures/file/simple.toml index bcdc07c6e..e9cb7cc67 100644 --- a/integration/fixtures/file/simple.toml +++ b/integration/fixtures/file/simple.toml @@ -33,10 +33,8 @@ logLevel = "DEBUG" [frontends.frontend1] backend = "backend2" [frontends.frontend1.routes.test_1] - rule = "Host" - value = "test.localhost" + rule = "Host:test.localhost" [frontends.frontend2] backend = "backend1" [frontends.frontend2.routes.test_2] - rule = "Path" - value = "/test" + rule = "Path:/test" diff --git a/integration/fixtures/https/https_sni.toml b/integration/fixtures/https/https_sni.toml index 2a1fa04a9..66f737a36 100644 --- a/integration/fixtures/https/https_sni.toml +++ b/integration/fixtures/https/https_sni.toml @@ -27,10 +27,8 @@ defaultEntryPoints = ["https"] [frontends.frontend1] backend = "backend1" [frontends.frontend1.routes.test_1] - rule = "Host" - value = "snitest.com" + rule = "Host:snitest.com" [frontends.frontend2] backend = "backend2" [frontends.frontend2.routes.test_2] - rule = "Host" - value = "snitest.org" + rule = "Host:snitest.org" diff --git a/middlewares/StripPrefix.go b/middlewares/stripPrefix.go similarity index 81% rename from middlewares/StripPrefix.go rename to middlewares/stripPrefix.go index 244d2862a..92eb7a5f1 100644 --- a/middlewares/StripPrefix.go +++ b/middlewares/stripPrefix.go @@ -20,3 +20,8 @@ func (s *StripPrefix) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) } } + +// SetHandler sets handler +func (s *StripPrefix) SetHandler(Handler http.Handler) { + s.Handler = Handler +} diff --git a/provider/consul_catalog.go b/provider/consul_catalog.go index c77d2dd23..01c823058 100644 --- a/provider/consul_catalog.go +++ b/provider/consul_catalog.go @@ -89,7 +89,7 @@ func (provider *ConsulCatalog) getBackend(node *api.ServiceEntry) string { } func (provider *ConsulCatalog) getFrontendValue(service string) string { - return service + "." + provider.Domain + return "Host:" + service + "." + provider.Domain } func (provider *ConsulCatalog) buildConfig(catalog []catalogUpdate) *types.Configuration { diff --git a/provider/consul_catalog_test.go b/provider/consul_catalog_test.go index c5086e627..9cf309838 100644 --- a/provider/consul_catalog_test.go +++ b/provider/consul_catalog_test.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/consul/api" ) -func TestConsulCatalogGetFrontendValue(t *testing.T) { +func TestConsulCatalogGetFrontendRule(t *testing.T) { provider := &ConsulCatalog{ Domain: "localhost", } @@ -19,7 +19,7 @@ func TestConsulCatalogGetFrontendValue(t *testing.T) { }{ { service: "foo", - expected: "foo.localhost", + expected: "Host:foo.localhost", }, } @@ -78,8 +78,7 @@ func TestConsulCatalogBuildConfig(t *testing.T) { Backend: "backend-test", Routes: map[string]types.Route{ "route-host-test": { - Rule: "Host", - Value: "test.localhost", + Rule: "Host:test.localhost", }, }, }, diff --git a/provider/docker.go b/provider/docker.go index 58939554f..e4190990b 100644 --- a/provider/docker.go +++ b/provider/docker.go @@ -2,7 +2,6 @@ package provider import ( "errors" - "fmt" "strconv" "strings" "text/template" @@ -108,7 +107,6 @@ func (provider *Docker) loadDockerConfig(containersInspected []docker.Container) "getProtocol": provider.getProtocol, "getPassHostHeader": provider.getPassHostHeader, "getEntryPoints": provider.getEntryPoints, - "getFrontendValue": provider.getFrontendValue, "getFrontendRule": provider.getFrontendRule, "replace": replace, } @@ -154,47 +152,37 @@ func containerFilter(container docker.Container) bool { return false } - labels, err := getLabels(container, []string{"traefik.frontend.rule", "traefik.frontend.value"}) - if len(labels) != 0 && err != nil { - log.Debugf("Filtering bad labeled container %s", container.Name) - return false - } - return true } func (provider *Docker) getFrontendName(container docker.Container) string { // Replace '.' with '-' in quoted keys because of this issue https://github.com/BurntSushi/toml/issues/78 - frontendName := fmt.Sprintf("%s-%s", provider.getFrontendRule(container), provider.getFrontendValue(container)) - frontendName = strings.Replace(frontendName, "[", "", -1) - frontendName = strings.Replace(frontendName, "]", "", -1) - - return strings.Replace(frontendName, ".", "-", -1) -} - -// GetFrontendValue returns the frontend value for the specified container, using -// it's label. It returns a default one if the label is not present. -func (provider *Docker) getFrontendValue(container docker.Container) string { - if label, err := getLabel(container, "traefik.frontend.value"); err == nil { - return label - } - return getEscapedName(container.Name) + "." + provider.Domain + return normalize(provider.getFrontendRule(container)) } // GetFrontendRule returns the frontend rule for the specified container, using // it's label. It returns a default one (Host) if the label is not present. func (provider *Docker) getFrontendRule(container docker.Container) string { + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + // TODO: backwards compatibility with DEPRECATED rule.Value + if value, ok := container.Config.Labels["traefik.frontend.value"]; ok { + log.Warnf("Label traefik.frontend.value=%s is DEPRECATED (will be removed in v1.0.0), please refer to the rule label: https://github.com/containous/traefik/blob/master/docs/index.md#docker", value) + rule, _ := container.Config.Labels["traefik.frontend.rule"] + return rule + ":" + value + } + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + if label, err := getLabel(container, "traefik.frontend.rule"); err == nil { return label } - return "Host" + return "Host:" + getEscapedName(container.Name) + "." + provider.Domain } func (provider *Docker) getBackend(container docker.Container) string { if label, err := getLabel(container, "traefik.backend"); err == nil { return label } - return getEscapedName(container.Name) + return normalize(container.Name) } func (provider *Docker) getPort(container docker.Container) string { @@ -211,7 +199,7 @@ func (provider *Docker) getWeight(container docker.Container) string { if label, err := getLabel(container, "traefik.weight"); err == nil { return label } - return "0" + return "1" } func (provider *Docker) getDomain(container docker.Container) string { diff --git a/provider/docker_test.go b/provider/docker_test.go index 2c51c0670..0dfb585f3 100644 --- a/provider/docker_test.go +++ b/provider/docker_test.go @@ -30,18 +30,18 @@ func TestDockerGetFrontendName(t *testing.T) { Name: "bar", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.rule": "Header", + "traefik.frontend.rule": "Headers:User-Agent,bat/0.1.0", }, }, }, - expected: "Header-bar-docker-localhost", + expected: "Headers-User-Agent-bat-0-1-0", }, { container: docker.Container{ Name: "test", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.value": "foo.bar", + "traefik.frontend.rule": "Host:foo.bar", }, }, }, @@ -52,24 +52,22 @@ func TestDockerGetFrontendName(t *testing.T) { Name: "test", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.value": "foo.bar", - "traefik.frontend.rule": "Header", + "traefik.frontend.rule": "Path:/test", }, }, }, - expected: "Header-foo-bar", + expected: "Path-test", }, { container: docker.Container{ Name: "test", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.value": "[foo.bar]", - "traefik.frontend.rule": "Header", + "traefik.frontend.rule": "PathPrefix:/test2", }, }, }, - expected: "Header-foo-bar", + expected: "PathPrefix-test2", }, } @@ -81,7 +79,7 @@ func TestDockerGetFrontendName(t *testing.T) { } } -func TestDockerGetFrontendValue(t *testing.T) { +func TestDockerGetFrontendRule(t *testing.T) { provider := &Docker{ Domain: "docker.localhost", } @@ -95,60 +93,36 @@ func TestDockerGetFrontendValue(t *testing.T) { Name: "foo", Config: &docker.Config{}, }, - expected: "foo.docker.localhost", + expected: "Host:foo.docker.localhost", }, { container: docker.Container{ Name: "bar", Config: &docker.Config{}, }, - expected: "bar.docker.localhost", + expected: "Host:bar.docker.localhost", }, { container: docker.Container{ Name: "test", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.value": "foo.bar", + "traefik.frontend.rule": "Host:foo.bar", }, }, }, - expected: "foo.bar", - }, - } - - for _, e := range containers { - actual := provider.getFrontendValue(e.container) - if actual != e.expected { - t.Fatalf("expected %q, got %q", e.expected, actual) - } - } -} - -func TestDockerGetFrontendRule(t *testing.T) { - provider := &Docker{} - - containers := []struct { - container docker.Container - expected string - }{ - { - container: docker.Container{ - Name: "foo", - Config: &docker.Config{}, - }, - expected: "Host", + expected: "Host:foo.bar", }, { container: docker.Container{ Name: "test", Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.rule": "foo", + "traefik.frontend.rule": "Path:/test", }, }, }, - expected: "foo", + expected: "Path:/test", }, } @@ -281,7 +255,7 @@ func TestDockerGetWeight(t *testing.T) { Name: "foo", Config: &docker.Config{}, }, - expected: "0", + expected: "1", }, { container: docker.Container{ @@ -535,7 +509,7 @@ func TestDockerTraefikFilter(t *testing.T) { container: docker.Container{ Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.rule": "Host", + "traefik.frontend.rule": "Host:foo.bar", }, }, NetworkSettings: &docker.NetworkSettings{ @@ -544,22 +518,7 @@ func TestDockerTraefikFilter(t *testing.T) { }, }, }, - expected: false, - }, - { - container: docker.Container{ - Config: &docker.Config{ - Labels: map[string]string{ - "traefik.frontend.value": "foo.bar", - }, - }, - NetworkSettings: &docker.NetworkSettings{ - Ports: map[docker.Port][]docker.PortBinding{ - "80/tcp": {}, - }, - }, - }, - expected: false, + expected: true, }, { container: docker.Container{ @@ -634,8 +593,7 @@ func TestDockerTraefikFilter(t *testing.T) { container: docker.Container{ Config: &docker.Config{ Labels: map[string]string{ - "traefik.frontend.rule": "Host", - "traefik.frontend.value": "foo.bar", + "traefik.frontend.rule": "Host:foo.bar", }, }, NetworkSettings: &docker.NetworkSettings{ @@ -651,7 +609,7 @@ func TestDockerTraefikFilter(t *testing.T) { for _, e := range containers { actual := containerFilter(e.container) if actual != e.expected { - t.Fatalf("expected %v, got %v", e.expected, actual) + t.Fatalf("expected %v for %+v, got %+v", e.expected, e, actual) } } } @@ -690,8 +648,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { EntryPoints: []string{}, Routes: map[string]types.Route{ `"route-frontend-Host-test-docker-localhost"`: { - Rule: "Host", - Value: "test.docker.localhost", + Rule: "Host:test.docker.localhost", }, }, }, @@ -700,7 +657,8 @@ func TestDockerLoadDockerConfig(t *testing.T) { "backend-test": { Servers: map[string]types.Server{ "server-test": { - URL: "http://127.0.0.1:80", + URL: "http://127.0.0.1:80", + Weight: 1, }, }, CircuitBreaker: nil, @@ -741,7 +699,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { "80/tcp": {}, }, Networks: map[string]docker.ContainerNetwork{ - "bridgde": { + "bridge": { IPAddress: "127.0.0.1", }, }, @@ -754,8 +712,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { EntryPoints: []string{"http", "https"}, Routes: map[string]types.Route{ `"route-frontend-Host-test1-docker-localhost"`: { - Rule: "Host", - Value: "test1.docker.localhost", + Rule: "Host:test1.docker.localhost", }, }, }, @@ -764,8 +721,7 @@ func TestDockerLoadDockerConfig(t *testing.T) { EntryPoints: []string{}, Routes: map[string]types.Route{ `"route-frontend-Host-test2-docker-localhost"`: { - Rule: "Host", - Value: "test2.docker.localhost", + Rule: "Host:test2.docker.localhost", }, }, }, @@ -774,10 +730,12 @@ func TestDockerLoadDockerConfig(t *testing.T) { "backend-foobar": { Servers: map[string]types.Server{ "server-test1": { - URL: "http://127.0.0.1:80", + URL: "http://127.0.0.1:80", + Weight: 1, }, "server-test2": { - URL: "http://127.0.0.1:80", + URL: "http://127.0.0.1:80", + Weight: 1, }, }, CircuitBreaker: nil, diff --git a/provider/marathon.go b/provider/marathon.go index 787b8e8fd..b255bbe5f 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -96,7 +96,6 @@ func (provider *Marathon) loadMarathonConfig() *types.Configuration { "getProtocol": provider.getProtocol, "getPassHostHeader": provider.getPassHostHeader, "getEntryPoints": provider.getEntryPoints, - "getFrontendValue": provider.getFrontendValue, "getFrontendRule": provider.getFrontendRule, "getFrontendBackend": provider.getFrontendBackend, "replace": replace, @@ -309,22 +308,21 @@ func (provider *Marathon) getEntryPoints(application marathon.Application) []str return []string{} } -// getFrontendValue returns the frontend value for the specified application, using -// it's label. It returns a default one if the label is not present. -func (provider *Marathon) getFrontendValue(application marathon.Application) string { - if label, err := provider.getLabel(application, "traefik.frontend.value"); err == nil { - return label - } - return getEscapedName(application.ID) + "." + provider.Domain -} - // getFrontendRule returns the frontend rule for the specified application, using // it's label. It returns a default one (Host) if the label is not present. func (provider *Marathon) getFrontendRule(application marathon.Application) string { + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + // TODO: backwards compatibility with DEPRECATED rule.Value + if value, err := provider.getLabel(application, "traefik.frontend.value"); err == nil { + log.Warnf("Label traefik.frontend.value=%s is DEPRECATED, please refer to the rule label: https://github.com/containous/traefik/blob/master/docs/index.md#marathon", value) + rule, _ := provider.getLabel(application, "traefik.frontend.rule") + return rule + ":" + value + } + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ if label, err := provider.getLabel(application, "traefik.frontend.rule"); err == nil { return label } - return "Host" + return "Host:" + getEscapedName(application.ID) + "." + provider.Domain } func (provider *Marathon) getBackend(task marathon.Task, applications []marathon.Application) string { diff --git a/provider/marathon_test.go b/provider/marathon_test.go index 32fd00698..def8d5595 100644 --- a/provider/marathon_test.go +++ b/provider/marathon_test.go @@ -86,8 +86,7 @@ func TestMarathonLoadConfig(t *testing.T) { EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-test`: { - Rule: "Host", - Value: "test.docker.localhost", + Rule: "Host:test.docker.localhost", }, }, }, @@ -831,7 +830,7 @@ func TestMarathonGetEntryPoints(t *testing.T) { } } -func TestMarathonGetFrontendValue(t *testing.T) { +func TestMarathonGetFrontendRule(t *testing.T) { provider := &Marathon{ Domain: "docker.localhost", } @@ -842,50 +841,21 @@ func TestMarathonGetFrontendValue(t *testing.T) { }{ { application: marathon.Application{}, - expected: ".docker.localhost", + expected: "Host:.docker.localhost", }, { application: marathon.Application{ ID: "test", }, - expected: "test.docker.localhost", + expected: "Host:test.docker.localhost", }, { application: marathon.Application{ Labels: map[string]string{ - "traefik.frontend.value": "foo.bar", + "traefik.frontend.rule": "Host:foo.bar", }, }, - expected: "foo.bar", - }, - } - - for _, a := range applications { - actual := provider.getFrontendValue(a.application) - if actual != a.expected { - t.Fatalf("expected %q, got %q", a.expected, actual) - } - } -} - -func TestMarathonGetFrontendRule(t *testing.T) { - provider := &Marathon{} - - applications := []struct { - application marathon.Application - expected string - }{ - { - application: marathon.Application{}, - expected: "Host", - }, - { - application: marathon.Application{ - Labels: map[string]string{ - "traefik.frontend.rule": "Header", - }, - }, - expected: "Header", + expected: "Host:foo.bar", }, } diff --git a/provider/provider.go b/provider/provider.go index 0213b5034..a1c0c660e 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -9,6 +9,7 @@ import ( "github.com/BurntSushi/toml" "github.com/containous/traefik/autogen" "github.com/containous/traefik/types" + "unicode" ) // Provider defines methods of a provider. @@ -67,3 +68,11 @@ func replace(s1 string, s2 string, s3 string) string { func getEscapedName(name string) string { return strings.Replace(strings.TrimPrefix(name, "/"), "/", "-", -1) } + +func normalize(name string) string { + fargs := func(c rune) bool { + return !unicode.IsLetter(c) && !unicode.IsNumber(c) + } + // get function + return strings.Join(strings.FieldsFunc(name, fargs), "-") +} diff --git a/rules.go b/rules.go new file mode 100644 index 000000000..8d43a884c --- /dev/null +++ b/rules.go @@ -0,0 +1,92 @@ +package main + +import ( + "errors" + "github.com/gorilla/mux" + "reflect" + "strings" +) + +// Rules holds rule parsing and configuration +type Rules struct { + route *serverRoute +} + +func (r *Rules) host(host string) *mux.Route { + return r.route.route.Host(host) +} + +func (r *Rules) path(path string) *mux.Route { + return r.route.route.Path(path) +} + +func (r *Rules) pathPrefix(path string) *mux.Route { + return r.route.route.PathPrefix(path) +} + +func (r *Rules) pathStrip(path string) *mux.Route { + r.route.stripPrefix = path + return r.route.route.Path(path) +} + +func (r *Rules) pathPrefixStrip(path string) *mux.Route { + r.route.stripPrefix = path + return r.route.route.PathPrefix(path) +} + +func (r *Rules) methods(methods ...string) *mux.Route { + return r.route.route.Methods(methods...) +} + +func (r *Rules) headers(headers ...string) *mux.Route { + return r.route.route.Headers(headers...) +} + +func (r *Rules) headersRegexp(headers ...string) *mux.Route { + return r.route.route.HeadersRegexp(headers...) +} + +// Parse parses rules expressions +func (r *Rules) Parse(expression string) (*mux.Route, error) { + functions := map[string]interface{}{ + "Host": r.host, + "Path": r.path, + "PathStrip": r.pathStrip, + "PathPrefix": r.pathPrefix, + "PathPrefixStrip": r.pathPrefixStrip, + "Methods": r.methods, + "Headers": r.headers, + "HeadersRegexp": r.headersRegexp, + } + f := func(c rune) bool { + return c == ':' || c == '=' + } + // get function + parsedFunctions := strings.FieldsFunc(expression, f) + if len(parsedFunctions) != 2 { + 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]) + } + + fargs := func(c rune) bool { + return c == ',' || c == ';' + } + // get function + parsedArgs := strings.FieldsFunc(parsedFunctions[1], fargs) + if len(parsedArgs) == 0 { + return nil, errors.New("Error parsing args from rule: " + expression) + } + + inputs := make([]reflect.Value, len(parsedArgs)) + for i := range parsedArgs { + inputs[i] = reflect.ValueOf(parsedArgs[i]) + } + method := reflect.ValueOf(parsedFunction) + if method.IsValid() { + return method.Call(inputs)[0].Interface().(*mux.Route), nil + } + return nil, errors.New("Method not found: " + parsedFunctions[0]) +} diff --git a/script/deploy.sh b/script/deploy.sh index 2671c0fb4..c906d4531 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -21,20 +21,18 @@ git config --global user.email "emile@vauge.com" git config --global user.name "Emile Vauge" git clone https://github.com/containous/traefik-library-image.git cd traefik-library-image -git remote rm origin -git remote add origin https://emilevauge:${GITHUB_TOKEN}@github.com/containous/traefik-library-image.git ./update.sh $VERSION git add -A echo $VERSION | git commit --file - echo $VERSION | git tag -a $VERSION --file - -git push --follow-tags -u origin master +git push -q --follow-tags https://emilevauge:${GITHUB_TOKEN}@github.com/containous/traefik-library-image.git # create docker image emilevauge/traefik (compatibility) docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS docker tag containous/traefik emilevauge/traefik:latest docker push emilevauge/traefik:latest docker tag emilevauge/traefik:latest emilevauge/traefik:${VERSION} -docker push emilevauge/traefik:${VERSION} +docker push -q emilevauge/traefik:${VERSION} cd .. rm -Rf traefik-library-image/ diff --git a/server.go b/server.go index 4f3f28489..95f8eb0be 100644 --- a/server.go +++ b/server.go @@ -55,6 +55,11 @@ type serverEntryPoint struct { httpRouter *middlewares.HandlerSwitcher } +type serverRoute struct { + route *mux.Route + stripPrefix string +} + // NewServer returns an initialized Server. func NewServer(globalConfiguration GlobalConfiguration) *Server { server := new(Server) @@ -354,23 +359,22 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo if _, ok := serverEntryPoints[entryPointName]; !ok { return nil, errors.New("Undefined entrypoint: " + entryPointName) } - newRoute := serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName) + newServerRoute := &serverRoute{route: serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName)} for routeName, route := range frontend.Routes { - log.Debugf("Creating route %s %s:%s", routeName, route.Rule, route.Value) - route, err := getRoute(newRoute, route.Rule, route.Value) + err := getRoute(newServerRoute, &route) if err != nil { return nil, err } - newRoute = route + log.Debugf("Creating route %s %s", routeName, route.Rule) } entryPoint := globalConfiguration.EntryPoints[entryPointName] if entryPoint.Redirect != nil { if redirectHandlers[entryPointName] != nil { - newRoute.Handler(redirectHandlers[entryPointName]) + newServerRoute.route.Handler(redirectHandlers[entryPointName]) } else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil { return nil, err } else { - newRoute.Handler(handler) + newServerRoute.route.Handler(handler) redirectHandlers[entryPointName] = handler } } else { @@ -448,9 +452,9 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo } else { log.Debugf("Reusing backend %s", frontend.Backend) } - server.wireFrontendBackend(frontend.Routes, newRoute, backends[frontend.Backend]) + server.wireFrontendBackend(newServerRoute, backends[frontend.Backend]) } - err := newRoute.GetError() + err := newServerRoute.route.GetError() if err != nil { log.Errorf("Error building route: %s", err) } @@ -460,29 +464,15 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo return serverEntryPoints, nil } -func (server *Server) wireFrontendBackend(routes map[string]types.Route, newRoute *mux.Route, handler http.Handler) { +func (server *Server) wireFrontendBackend(serverRoute *serverRoute, handler http.Handler) { // strip prefix - var strip bool - for _, route := range routes { - switch route.Rule { - case "PathStrip": - newRoute.Handler(&middlewares.StripPrefix{ - Prefix: route.Value, - Handler: handler, - }) - strip = true - break - case "PathPrefixStrip": - newRoute.Handler(&middlewares.StripPrefix{ - Prefix: route.Value, - Handler: handler, - }) - strip = true - break - } - } - if !strip { - newRoute.Handler(handler) + if len(serverRoute.stripPrefix) > 0 { + serverRoute.route.Handler(&middlewares.StripPrefix{ + Prefix: serverRoute.stripPrefix, + Handler: handler, + }) + } else { + serverRoute.route.Handler(handler) } } @@ -522,32 +512,29 @@ func (server *Server) buildDefaultHTTPRouter() *mux.Router { return router } -func getRoute(any interface{}, rule string, value ...interface{}) (*mux.Route, error) { - switch rule { - case "PathStrip": - rule = "Path" - case "PathPrefixStrip": - rule = "PathPrefix" +func getRoute(serverRoute *serverRoute, route *types.Route) error { + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + // TODO: backwards compatibility with DEPRECATED rule.Value + if len(route.Value) > 0 { + route.Rule += ":" + route.Value + log.Warnf("Value %s is DEPRECATED (will be removed in v1.0.0), please refer to the new frontend notation: https://github.com/containous/traefik/blob/master/docs/index.md#-frontends", route.Value) } - inputs := make([]reflect.Value, len(value)) - for i := range value { - inputs[i] = reflect.ValueOf(value[i]) + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + + rules := Rules{route: serverRoute} + newRoute, err := rules.Parse(route.Rule) + if err != nil { + return err } - method := reflect.ValueOf(any).MethodByName(rule) - if method.IsValid() { - return method.Call(inputs)[0].Interface().(*mux.Route), nil - } - return nil, errors.New("Method not found: " + rule) + serverRoute.route = newRoute + return nil } func sortedFrontendNamesForConfig(configuration *types.Configuration) []string { keys := []string{} - for key := range configuration.Frontends { keys = append(keys, key) } - sort.Strings(keys) - return keys } diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index 65a7a0d3c..a51cd341b 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -8,6 +8,5 @@ backend = "backend-{{.}}" passHostHeader = false [frontends.frontend-{{.}}.routes.route-host-{{.}}] - rule = "Host" - value = "{{getFrontendValue .}}" + rule = "{{getFrontendValue .}}" {{end}} diff --git a/templates/docker.tmpl b/templates/docker.tmpl index 7826acc56..f43bef8b4 100644 --- a/templates/docker.tmpl +++ b/templates/docker.tmpl @@ -13,5 +13,4 @@ {{end}}] [frontends."frontend-{{$frontend}}".routes."route-frontend-{{$frontend}}"] rule = "{{getFrontendRule $container}}" - value = "{{getFrontendValue $container}}" {{end}} diff --git a/templates/kv.tmpl b/templates/kv.tmpl index 9fd770d24..97793784f 100644 --- a/templates/kv.tmpl +++ b/templates/kv.tmpl @@ -37,6 +37,5 @@ {{range $routes}} [frontends.{{$frontend}}.routes.{{Last .}}] rule = "{{Get "" . "/rule"}}" - value = "{{Get "" . "/value"}}" {{end}} {{end}} diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index ba60b5012..d2243cf47 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -14,5 +14,4 @@ {{end}}] [frontends.frontend{{.ID | replace "/" "-"}}.routes.route-host{{.ID | replace "/" "-"}}] rule = "{{getFrontendRule .}}" - value = "{{getFrontendValue .}}" {{end}} diff --git a/tests/whoami.json b/tests/whoami.json index 138a2264d..daebbfa26 100644 --- a/tests/whoami.json +++ b/tests/whoami.json @@ -25,6 +25,7 @@ ], "labels": { "traefik.weight": "1", - "traefik.protocole": "http" + "traefik.protocole": "http", + "traefik.frontend.rule" : "Headers:Host,test.localhost" } } diff --git a/traefik.sample.toml b/traefik.sample.toml index 6985d55f8..945f963a3 100644 --- a/traefik.sample.toml +++ b/traefik.sample.toml @@ -513,17 +513,14 @@ # [frontends.frontend1] # backend = "backend2" # [frontends.frontend1.routes.test_1] -# rule = "Host" -# value = "test.localhost" +# rule = "Host:test.localhost" # [frontends.frontend2] # backend = "backend1" # passHostHeader = true # entrypoints = ["https"] # overrides defaultEntryPoints # [frontends.frontend2.routes.test_1] -# rule = "Host" -# value = "{subdomain:[a-z]+}.localhost" +# rule = "Host:{subdomain:[a-z]+}.localhost" # [frontends.frontend3] # entrypoints = ["http", "https"] # overrides defaultEntryPoints # backend = "backend2" -# rule = "Path" -# value = "/test" +# rule = "Path:/test" \ No newline at end of file diff --git a/types/types.go b/types/types.go index 30bfbf483..2168ac49f 100644 --- a/types/types.go +++ b/types/types.go @@ -30,8 +30,11 @@ type Server struct { // Route holds route configuration. type Route struct { - Rule string `json:"rule,omitempty"` + Rule string `json:"rule,omitempty"` + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ + // TODO: backwards compatibility with DEPRECATED rule.Value Value string `json:"value,omitempty"` + // ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ } // Frontend holds frontend configuration. diff --git a/webui/src/app/sections/providers/frontend-monitor/frontend-monitor.html b/webui/src/app/sections/providers/frontend-monitor/frontend-monitor.html index 48c8e67ba..6881c4bd8 100644 --- a/webui/src/app/sections/providers/frontend-monitor/frontend-monitor.html +++ b/webui/src/app/sections/providers/frontend-monitor/frontend-monitor.html @@ -7,12 +7,10 @@ Route Rule - Value {{routeId}} - {{route.rule}} - {{route.value}} + {{route.rule}} diff --git a/webui/src/index.html b/webui/src/index.html index fbb832c71..20d356187 100644 --- a/webui/src/index.html +++ b/webui/src/index.html @@ -30,7 +30,7 @@