1
0
mirror of https://github.com/containous/traefik.git synced 2025-09-15 13:44:21 +03:00

Compare commits

...

16 Commits
v1.2.1 ... v1.2

Author SHA1 Message Date
mmatur
cab746bcca fix: docs build trusted host 2024-05-16 21:09:50 +02:00
mmatur
15e9426e19 fix: docs build alpine version 2024-05-16 16:27:09 +02:00
mmatur
cf31e02b9c feat: add dockerfile for documentation 2021-10-05 10:28:50 +02:00
Fernandez Ludovic
2ac217c741 doc: fix version in requirements.txt 2018-08-06 17:02:09 +02:00
Michael
bc875d6268 [doc] fix version in requirements.txt
To be able to generate versionned documentation
2018-01-19 15:46:22 +01:00
Emile Vauge
bbb8d922fc Merge pull request #1435 from containous/prepare-release-v1.2.3
Prepare release v1.2.3
2017-04-13 21:09:40 +02:00
Emile Vauge
37b44cc706 Prepare release v1.2.3
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-13 20:06:25 +02:00
Emile Vauge
3c6e0b3e68 Merge pull request #1433 from containous/fix-too-many-redirects
Fix too many redirect
2017-04-13 20:04:34 +02:00
Emile Vauge
e21feae561 Fix too many redirect
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-13 17:59:24 +02:00
Emile Vauge
c766439fed Merge pull request #1420 from containous/prepare-release-v1.2.2
Prepare release v1.2.2
2017-04-11 22:05:04 +02:00
Emile Vauge
0ecfbb8279 Prepare release v1.2.2
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-11 20:13:18 +02:00
Emile Vauge
82d631572c Merge pull request #1417 from containous/carry-pr-1271
Carry PR 1271
2017-04-11 20:10:14 +02:00
Adam Geiger
fa4d2d325d Fix redirect empty backend
Issue-#679
2017-04-11 18:00:57 +02:00
Emile Vauge
c469bbb70c Merge pull request #1401 from containous/fix-postloadconfig-acme
Fix postloadconfig acme & Docker filter empty rule
2017-04-11 17:56:38 +02:00
Emile Vauge
b3e6c7f598 Fix Docker filter empty rule
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-07 16:30:57 +02:00
Emile Vauge
40afd641a9 Fix postLoadConfig
Signed-off-by: Emile Vauge <emile@vauge.com>
2017-04-07 15:48:58 +02:00
6 changed files with 338 additions and 197 deletions

View File

@@ -1,5 +1,20 @@
# Change Log
## [v1.2.3](https://github.com/containous/traefik/tree/v1.2.3) (2017-04-13)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.2...v1.2.3)
**Merged pull requests:**
- Fix too many redirect [\#1433](https://github.com/containous/traefik/pull/1433) ([emilevauge](https://github.com/emilevauge))
## [v1.2.2](https://github.com/containous/traefik/tree/v1.2.2) (2017-04-11)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.1...v1.2.2)
**Merged pull requests:**
- Carry PR 1271 [\#1417](https://github.com/containous/traefik/pull/1417) ([emilevauge](https://github.com/emilevauge))
- Fix postloadconfig acme & Docker filter empty rule [\#1401](https://github.com/containous/traefik/pull/1401) ([emilevauge](https://github.com/emilevauge))
## [v1.2.1](https://github.com/containous/traefik/tree/v1.2.1) (2017-03-27)
[Full Changelog](https://github.com/containous/traefik/compare/v1.2.0...v1.2.1)

10
docs.Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM alpine:3.7
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/bin
COPY requirements.txt /mkdocs/
WORKDIR /mkdocs
VOLUME /mkdocs
RUN apk --no-cache --no-progress add py-pip \
&& pip install --trusted-host pypi.python.org --user -r requirements.txt

View File

@@ -380,6 +380,11 @@ func (provider *Docker) containerFilter(container dockerData) bool {
return false
}
if len(provider.getFrontendRule(container)) == 0 {
log.Debugf("Filtering container with empty frontend rule %s", container.Name)
return false
}
return true
}
@@ -394,7 +399,10 @@ func (provider *Docker) getFrontendRule(container dockerData) string {
if label, err := getLabel(container, "traefik.frontend.rule"); err == nil {
return label
}
return "Host:" + provider.getSubDomain(container.ServiceName) + "." + provider.Domain
if len(provider.Domain) > 0 {
return "Host:" + provider.getSubDomain(container.ServiceName) + "." + provider.Domain
}
return ""
}
func (provider *Docker) getBackend(container dockerData) string {

View File

@@ -742,11 +742,10 @@ func TestDockerGetLabels(t *testing.T) {
}
func TestDockerTraefikFilter(t *testing.T) {
provider := Docker{}
containers := []struct {
container docker.ContainerJSON
exposedByDefault bool
expected bool
container docker.ContainerJSON
expected bool
provider *Docker
}{
{
container: docker.ContainerJSON{
@@ -756,8 +755,11 @@ func TestDockerTraefikFilter(t *testing.T) {
Config: &container.Config{},
NetworkSettings: &docker.NetworkSettings{},
},
exposedByDefault: true,
expected: false,
expected: false,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
},
{
container: docker.ContainerJSON{
@@ -777,8 +779,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: false,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: false,
},
{
container: docker.ContainerJSON{
@@ -798,8 +803,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -816,8 +824,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -833,8 +844,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -855,8 +869,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -876,8 +893,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -897,8 +917,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -918,8 +941,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: true,
},
expected: true,
},
{
container: docker.ContainerJSON{
@@ -935,8 +961,11 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: false,
expected: false,
provider: &Docker{
Domain: "test",
ExposedByDefault: false,
},
expected: false,
},
{
container: docker.ContainerJSON{
@@ -956,8 +985,58 @@ func TestDockerTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: false,
expected: true,
provider: &Docker{
Domain: "test",
ExposedByDefault: false,
},
expected: true,
},
{
container: docker.ContainerJSON{
ContainerJSONBase: &docker.ContainerJSONBase{
Name: "container",
},
Config: &container.Config{
Labels: map[string]string{
"traefik.enable": "true",
},
},
NetworkSettings: &docker.NetworkSettings{
NetworkSettingsBase: docker.NetworkSettingsBase{
Ports: nat.PortMap{
"80/tcp": {},
},
},
},
},
provider: &Docker{
ExposedByDefault: false,
},
expected: false,
},
{
container: docker.ContainerJSON{
ContainerJSONBase: &docker.ContainerJSONBase{
Name: "container",
},
Config: &container.Config{
Labels: map[string]string{
"traefik.enable": "true",
"traefik.frontend.rule": "Host:i.love.this.host",
},
},
NetworkSettings: &docker.NetworkSettings{
NetworkSettingsBase: docker.NetworkSettingsBase{
Ports: nat.PortMap{
"80/tcp": {},
},
},
},
},
provider: &Docker{
ExposedByDefault: false,
},
expected: true,
},
}
@@ -965,9 +1044,8 @@ func TestDockerTraefikFilter(t *testing.T) {
e := e
t.Run(strconv.Itoa(containerID), func(t *testing.T) {
t.Parallel()
provider.ExposedByDefault = e.exposedByDefault
dockerData := parseContainer(e.container)
actual := provider.containerFilter(dockerData)
actual := e.provider.containerFilter(dockerData)
if actual != e.expected {
t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual)
}
@@ -1941,14 +2019,11 @@ func TestSwarmGetLabels(t *testing.T) {
}
func TestSwarmTraefikFilter(t *testing.T) {
provider := &Docker{
SwarmMode: true,
}
services := []struct {
service swarm.Service
exposedByDefault bool
expected bool
networks map[string]*docker.NetworkResource
service swarm.Service
expected bool
networks map[string]*docker.NetworkResource
provider *Docker
}{
{
service: swarm.Service{
@@ -1958,9 +2033,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: false,
networks: map[string]*docker.NetworkResource{},
expected: false,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -1974,9 +2053,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: false,
networks: map[string]*docker.NetworkResource{},
expected: false,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -1990,9 +2073,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -2005,9 +2092,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -2021,9 +2112,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -2037,9 +2132,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -2053,9 +2152,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: true,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: true,
},
},
{
service: swarm.Service{
@@ -2068,9 +2171,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: false,
expected: false,
networks: map[string]*docker.NetworkResource{},
expected: false,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: false,
},
},
{
service: swarm.Service{
@@ -2084,9 +2191,13 @@ func TestSwarmTraefikFilter(t *testing.T) {
},
},
},
exposedByDefault: false,
expected: true,
networks: map[string]*docker.NetworkResource{},
expected: true,
networks: map[string]*docker.NetworkResource{},
provider: &Docker{
SwarmMode: true,
Domain: "test",
ExposedByDefault: false,
},
},
}
@@ -2095,8 +2206,7 @@ func TestSwarmTraefikFilter(t *testing.T) {
t.Run(strconv.Itoa(serviceID), func(t *testing.T) {
t.Parallel()
dockerData := parseService(e.service, e.networks)
provider.ExposedByDefault = e.exposedByDefault
actual := provider.containerFilter(dockerData)
actual := e.provider.containerFilter(dockerData)
if actual != e.expected {
t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual)
}

View File

@@ -1,3 +1,3 @@
mkdocs>=0.16.1
pymdown-extensions>=1.4
mkdocs-bootswatch>=0.4.0
mkdocs>=0.16.1,<0.17.0
pymdown-extensions==1.4
mkdocs-bootswatch==0.4.0

256
server.go
View File

@@ -311,15 +311,16 @@ func (server *Server) postLoadConfig() {
for _, frontend := range configuration.Frontends {
// check if one of the frontend entrypoints is configured with TLS
TLSEnabled := false
// and is configured with ACME
ACMEEnabled := false
for _, entrypoint := range frontend.EntryPoints {
if server.globalConfiguration.EntryPoints[entrypoint].TLS != nil {
TLSEnabled = true
if server.globalConfiguration.ACME.EntryPoint == entrypoint && server.globalConfiguration.EntryPoints[entrypoint].TLS != nil {
ACMEEnabled = true
break
}
}
if TLSEnabled {
if ACMEEnabled {
for _, route := range frontend.Routes {
rules := Rules{}
domains, err := rules.ParseDomains(route.Rule)
@@ -552,13 +553,11 @@ func (server *Server) buildEntryPoints(globalConfiguration GlobalConfiguration)
// provider configurations.
func (server *Server) loadConfig(configurations configs, globalConfiguration GlobalConfiguration) (map[string]*serverEntryPoint, error) {
serverEntryPoints := server.buildEntryPoints(globalConfiguration)
redirectHandlers := make(map[string]http.Handler)
redirectHandlers := make(map[string]negroni.Handler)
backends := map[string]http.Handler{}
backendsHealthcheck := map[string]*healthcheck.BackendHealthCheck{}
backend2FrontendMap := map[string]string{}
for _, configuration := range configurations {
frontendNames := sortedFrontendNamesForConfig(configuration)
frontend:
@@ -597,99 +596,66 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
log.Debugf("Creating route %s %s", routeName, route.Rule)
}
entryPoint := globalConfiguration.EntryPoints[entryPointName]
negroni := negroni.New()
if entryPoint.Redirect != nil {
if redirectHandlers[entryPointName] != nil {
newServerRoute.route.Handler(redirectHandlers[entryPointName])
negroni.Use(redirectHandlers[entryPointName])
} else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil {
log.Errorf("Error loading entrypoint configuration for frontend %s: %v", frontendName, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
} else {
newServerRoute.route.Handler(handler)
negroni.Use(handler)
redirectHandlers[entryPointName] = handler
}
} else {
if backends[frontend.Backend] == nil {
log.Debugf("Creating backend %s", frontend.Backend)
var lb http.Handler
rr, _ := roundrobin.New(saveBackend)
if configuration.Backends[frontend.Backend] == nil {
log.Errorf("Undefined backend '%s' for frontend %s", frontend.Backend, frontendName)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
}
if backends[entryPointName+frontend.Backend] == nil {
log.Debugf("Creating backend %s", frontend.Backend)
var lb http.Handler
rr, _ := roundrobin.New(saveBackend)
if configuration.Backends[frontend.Backend] == nil {
log.Errorf("Undefined backend '%s' for frontend %s", frontend.Backend, frontendName)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
if err != nil {
log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
if err != nil {
log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
cookiename := "_TRAEFIK_BACKEND"
var sticky *roundrobin.StickySession
stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
cookiename := "_TRAEFIK_BACKEND"
var sticky *roundrobin.StickySession
if stickysession {
sticky = roundrobin.NewStickySession(cookiename)
}
switch lbMethod {
case types.Drr:
log.Debugf("Creating load-balancer drr")
rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
if stickysession {
sticky = roundrobin.NewStickySession(cookiename)
log.Debugf("Sticky session with cookie %v", cookiename)
rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
}
switch lbMethod {
case types.Drr:
log.Debugf("Creating load-balancer drr")
rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
if stickysession {
log.Debugf("Sticky session with cookie %v", cookiename)
rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
lb = rebalancer
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL)
if err != nil {
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
lb = rebalancer
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL)
if err != nil {
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
backend2FrontendMap[url.String()] = frontendName
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
if configuration.Backends[frontend.Backend].HealthCheck != nil {
var interval time.Duration
if configuration.Backends[frontend.Backend].HealthCheck.Interval != "" {
interval, err = time.ParseDuration(configuration.Backends[frontend.Backend].HealthCheck.Interval)
if err != nil {
log.Errorf("Wrong healthcheck interval: %s", err)
interval = time.Second * 30
}
}
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.Path, interval, rebalancer)
}
}
case types.Wrr:
log.Debugf("Creating load-balancer wrr")
if stickysession {
log.Debugf("Sticky session with cookie %v", cookiename)
rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
}
lb = rr
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL)
if err != nil {
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
backend2FrontendMap[url.String()] = frontendName
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
backend2FrontendMap[url.String()] = frontendName
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
if configuration.Backends[frontend.Backend].HealthCheck != nil {
var interval time.Duration
@@ -700,63 +666,96 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
interval = time.Second * 30
}
}
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.Path, interval, rr)
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.Path, interval, rebalancer)
}
}
maxConns := configuration.Backends[frontend.Backend].MaxConn
if maxConns != nil && maxConns.Amount != 0 {
extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
case types.Wrr:
log.Debugf("Creating load-balancer wrr")
if stickysession {
log.Debugf("Sticky session with cookie %v", cookiename)
rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
}
lb = rr
for serverName, server := range configuration.Backends[frontend.Backend].Servers {
url, err := url.Parse(server.URL)
if err != nil {
log.Errorf("Error creating connlimit: %v", err)
log.Errorf("Error parsing server URL %s: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
log.Debugf("Creating loadd-balancer connlimit")
lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
if err != nil {
log.Errorf("Error creating connlimit: %v", err)
backend2FrontendMap[url.String()] = frontendName
log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
}
// retry ?
if globalConfiguration.Retry != nil {
retries := len(configuration.Backends[frontend.Backend].Servers)
if globalConfiguration.Retry.Attempts > 0 {
retries = globalConfiguration.Retry.Attempts
if configuration.Backends[frontend.Backend].HealthCheck != nil {
var interval time.Duration
if configuration.Backends[frontend.Backend].HealthCheck.Interval != "" {
interval, err = time.ParseDuration(configuration.Backends[frontend.Backend].HealthCheck.Interval)
if err != nil {
log.Errorf("Wrong healthcheck interval: %s", err)
interval = time.Second * 30
}
}
lb = middlewares.NewRetry(retries, lb)
log.Debugf("Creating retries max attempts %d", retries)
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(configuration.Backends[frontend.Backend].HealthCheck.Path, interval, rr)
}
}
maxConns := configuration.Backends[frontend.Backend].MaxConn
if maxConns != nil && maxConns.Amount != 0 {
extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
if err != nil {
log.Errorf("Error creating connlimit: %v", err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
log.Debugf("Creating loadd-balancer connlimit")
lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
if err != nil {
log.Errorf("Error creating connlimit: %v", err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
}
// retry ?
if globalConfiguration.Retry != nil {
retries := len(configuration.Backends[frontend.Backend].Servers)
if globalConfiguration.Retry.Attempts > 0 {
retries = globalConfiguration.Retry.Attempts
}
lb = middlewares.NewRetry(retries, lb)
log.Debugf("Creating retries max attempts %d", retries)
}
var negroni = negroni.New()
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
metricsMiddlewareBackend := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(frontend.Backend, server.globalConfiguration.Web.Metrics.Prometheus))
negroni.Use(metricsMiddlewareBackend)
}
if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil {
if server.globalConfiguration.Web.Metrics.Prometheus != nil {
metricsMiddlewareBackend := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(frontend.Backend, server.globalConfiguration.Web.Metrics.Prometheus))
negroni.Use(metricsMiddlewareBackend)
}
if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
cbreaker, err := middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger))
if err != nil {
log.Errorf("Error creating circuit breaker: %v", err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
negroni.Use(cbreaker)
} else {
negroni.UseHandler(lb)
}
if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
cbreaker, err := middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger))
if err != nil {
log.Errorf("Error creating circuit breaker: %v", err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
backends[frontend.Backend] = negroni
negroni.Use(cbreaker)
} else {
log.Debugf("Reusing backend %s", frontend.Backend)
negroni.UseHandler(lb)
}
if frontend.Priority > 0 {
newServerRoute.route.Priority(frontend.Priority)
}
server.wireFrontendBackend(newServerRoute, backends[frontend.Backend])
backends[entryPointName+frontend.Backend] = negroni
} else {
log.Debugf("Reusing backend %s", frontend.Backend)
}
if frontend.Priority > 0 {
newServerRoute.route.Priority(frontend.Priority)
}
server.wireFrontendBackend(newServerRoute, backends[entryPointName+frontend.Backend])
err := newServerRoute.route.GetError()
if err != nil {
log.Errorf("Error building route: %s", err)
@@ -793,7 +792,7 @@ func (server *Server) wireFrontendBackend(serverRoute *serverRoute, handler http
serverRoute.route.Handler(handler)
}
func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *EntryPoint) (http.Handler, error) {
func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *EntryPoint) (negroni.Handler, error) {
regex := entryPoint.Redirect.Regex
replacement := entryPoint.Redirect.Replacement
if len(entryPoint.Redirect.EntryPoint) > 0 {
@@ -817,9 +816,8 @@ func (server *Server) loadEntryPointConfig(entryPointName string, entryPoint *En
return nil, err
}
log.Debugf("Creating entryPoint redirect %s -> %s : %s -> %s", entryPointName, entryPoint.Redirect.EntryPoint, regex, replacement)
negroni := negroni.New()
negroni.Use(rewrite)
return negroni, nil
return rewrite, nil
}
func (server *Server) buildDefaultHTTPRouter() *mux.Router {