Merge v2.10 into v3.0
This commit is contained in:
commit
286181aa61
62 changed files with 712 additions and 189 deletions
|
@ -3,6 +3,7 @@ package integration
|
|||
import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -335,6 +336,71 @@ func (s *AccessLogSuite) TestAccessLogFrontendRedirect(c *check.C) {
|
|||
checkNoOtherTraefikProblems(c)
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogJSONFrontendRedirect(c *check.C) {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
type logLine struct {
|
||||
DownstreamStatus int `json:"downstreamStatus"`
|
||||
OriginStatus int `json:"originStatus"`
|
||||
RouterName string `json:"routerName"`
|
||||
ServiceName string `json:"serviceName"`
|
||||
}
|
||||
|
||||
expected := []logLine{
|
||||
{
|
||||
DownstreamStatus: 302,
|
||||
OriginStatus: 0,
|
||||
RouterName: "rt-frontendRedirect@docker",
|
||||
ServiceName: "",
|
||||
},
|
||||
{
|
||||
DownstreamStatus: 200,
|
||||
OriginStatus: 200,
|
||||
RouterName: "rt-server0@docker",
|
||||
ServiceName: "service1@docker",
|
||||
},
|
||||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_json_config.toml"))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "frontendRedirect")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
|
||||
// Test frontend redirect
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8005/test", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = ""
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.HasBody())
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
lines := extractLines(c)
|
||||
c.Assert(len(lines), checker.GreaterOrEqualThan, len(expected))
|
||||
|
||||
for i, line := range lines {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
var logline logLine
|
||||
err := json.Unmarshal([]byte(line), &logline)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(logline.DownstreamStatus, checker.Equals, expected[i].DownstreamStatus)
|
||||
c.Assert(logline.OriginStatus, checker.Equals, expected[i].OriginStatus)
|
||||
c.Assert(logline.RouterName, checker.Equals, expected[i].RouterName)
|
||||
c.Assert(logline.ServiceName, checker.Equals, expected[i].ServiceName)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogRateLimit(c *check.C) {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
|
@ -526,6 +592,53 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
|
|||
checkNoOtherTraefikProblems(c)
|
||||
}
|
||||
|
||||
func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
|
||||
ensureWorkingDirectoryIsClean()
|
||||
|
||||
expected := []accessLogValue{
|
||||
{
|
||||
formatOnly: false,
|
||||
code: "200",
|
||||
user: "-",
|
||||
routerName: "rt-preflightCORS",
|
||||
serviceURL: "-",
|
||||
},
|
||||
}
|
||||
|
||||
// Start Traefik
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
checkStatsForLogFile(c)
|
||||
|
||||
waitForTraefik(c, "preflightCORS")
|
||||
|
||||
// Verify Traefik started OK
|
||||
checkTraefikStarted(c)
|
||||
|
||||
// Test preflight response
|
||||
req, err := http.NewRequest(http.MethodOptions, "http://127.0.0.1:8009/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = "preflight.docker.local"
|
||||
req.Header.Set("Origin", "whatever")
|
||||
req.Header.Set("Access-Control-Request-Method", "GET")
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Verify access.log output as expected
|
||||
count := checkAccessLogExactValuesOutput(c, expected)
|
||||
|
||||
c.Assert(count, checker.GreaterOrEqualThan, len(expected))
|
||||
|
||||
// Verify no other Traefik problems
|
||||
checkNoOtherTraefikProblems(c)
|
||||
}
|
||||
|
||||
func checkNoOtherTraefikProblems(c *check.C) {
|
||||
traefikLog, err := os.ReadFile(traefikTestLogFile)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -28,6 +29,13 @@ type ConsulSuite struct {
|
|||
consulURL string
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) resetStore(c *check.C) {
|
||||
err := s.kvClient.DeleteTree(context.Background(), "traefik")
|
||||
if err != nil && !errors.Is(err, store.ErrKeyNotFound) {
|
||||
c.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) setupStore(c *check.C) {
|
||||
s.createComposeProject(c, "consul")
|
||||
s.composeUp(c)
|
||||
|
@ -154,3 +162,71 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
c.Error(text)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) assertWhoami(c *check.C, host string, expectedStatusCode int) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
req.Host = host
|
||||
|
||||
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
|
||||
resp.Body.Close()
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *ConsulSuite) TestDeleteRootKey(c *check.C) {
|
||||
// This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092
|
||||
s.setupStore(c)
|
||||
s.resetStore(c)
|
||||
|
||||
file := s.adaptFile(c, "fixtures/consul/simple.toml", struct{ ConsulAddress string }{s.consulURL})
|
||||
defer os.Remove(file)
|
||||
|
||||
ctx := context.Background()
|
||||
svcaddr := net.JoinHostPort(s.getComposeServiceIP(c, "whoami"), "80")
|
||||
|
||||
data := map[string]string{
|
||||
"traefik/http/routers/Router0/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)",
|
||||
"traefik/http/routers/Router0/service": "simplesvc0",
|
||||
|
||||
"traefik/http/routers/Router1/entryPoints/0": "web",
|
||||
"traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)",
|
||||
"traefik/http/routers/Router1/service": "simplesvc1",
|
||||
|
||||
"traefik/http/services/simplesvc0/loadBalancer/servers/0/url": "http://" + svcaddr,
|
||||
"traefik/http/services/simplesvc1/loadBalancer/servers/0/url": "http://" + svcaddr,
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
err := s.kvClient.Put(ctx, k, []byte(v), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
// wait for traefik
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second,
|
||||
try.BodyContains(`"Router0@consul":`, `"Router1@consul":`, `"simplesvc0@consul":`, `"simplesvc1@consul":`),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusOK)
|
||||
|
||||
// delete router1
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik/http/routers/Router1")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusOK)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
|
||||
// delete simple services and router0
|
||||
err = s.kvClient.DeleteTree(ctx, "traefik")
|
||||
c.Assert(err, checker.IsNil)
|
||||
s.assertWhoami(c, "kv1.localhost", http.StatusNotFound)
|
||||
s.assertWhoami(c, "kv2.localhost", http.StatusNotFound)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
address = ":8007"
|
||||
[entryPoints.digestAuth]
|
||||
address = ":8008"
|
||||
[entryPoints.preflight]
|
||||
address = ":8009"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
|
32
integration/fixtures/access_log_json_config.toml
Normal file
32
integration/fixtures/access_log_json_config.toml
Normal file
|
@ -0,0 +1,32 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "ERROR"
|
||||
filePath = "traefik.log"
|
||||
|
||||
[accessLog]
|
||||
format = "json"
|
||||
filePath = "access.log"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
[entryPoints.frontendRedirect]
|
||||
address = ":8005"
|
||||
[entryPoints.httpFrontendAuth]
|
||||
address = ":8006"
|
||||
[entryPoints.httpRateLimit]
|
||||
address = ":8007"
|
||||
[entryPoints.digestAuth]
|
||||
address = ":8008"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
exposedByDefault = false
|
||||
defaultRule = "Host(`{{ normalize .Name }}.docker.local`)"
|
||||
watch = true
|
|
@ -0,0 +1,31 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
## dynamic configuration ##
|
||||
|
||||
[http.routers]
|
||||
[http.routers.router1]
|
||||
rule = "Host(`test.localhost`)"
|
||||
middlewares = ["remove"]
|
||||
service = "service1"
|
||||
|
||||
[http.middlewares]
|
||||
[http.middlewares.remove.headers.customRequestHeaders]
|
||||
X-Forwarded-For = ""
|
||||
Foo = ""
|
||||
|
||||
[http.services]
|
||||
[http.services.service1.loadBalancer]
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "http://127.0.0.1:9000"
|
|
@ -1,7 +1,9 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
|
@ -25,6 +27,46 @@ func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestReverseProxyHeaderRemoved(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/remove_reverseproxy_headers.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
defer display(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, found := r.Header["X-Forwarded-Host"]
|
||||
c.Assert(found, checker.True)
|
||||
_, found = r.Header["Foo"]
|
||||
c.Assert(found, checker.False)
|
||||
_, found = r.Header["X-Forwarded-For"]
|
||||
c.Assert(found, checker.False)
|
||||
})
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:9000")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
ts := &httptest.Server{
|
||||
Listener: listener,
|
||||
Config: &http.Server{Handler: handler},
|
||||
}
|
||||
ts.Start()
|
||||
defer ts.Close()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
req.Host = "test.localhost"
|
||||
req.Header = http.Header{
|
||||
"Foo": {"bar"},
|
||||
}
|
||||
|
||||
err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *HeadersSuite) TestCorsResponses(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/headers/cors.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
|
|
|
@ -85,6 +85,16 @@ services:
|
|||
traefik.http.middlewares.wl.ipallowlist.sourcerange: 8.8.8.8/32
|
||||
traefik.http.services.service3.loadbalancer.server.port: 80
|
||||
|
||||
preflightCORS:
|
||||
image: traefik/whoami
|
||||
labels:
|
||||
traefik.enable: true
|
||||
traefik.http.routers.rt-preflightCORS.entryPoints: preflight
|
||||
traefik.http.routers.rt-preflightCORS.rule: Host(`preflight.docker.local`)
|
||||
traefik.http.routers.rt-preflightCORS.middlewares: preflightCORS
|
||||
traefik.http.middlewares.preflightCORS.headers.accessControlAllowMethods: OPTIONS, GET
|
||||
traefik.http.services.preflightCORS.loadbalancer.server.port: 80
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: traefik-test-network
|
||||
|
|
|
@ -2,6 +2,8 @@ version: "3.8"
|
|||
services:
|
||||
consul:
|
||||
image: consul:1.6
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
|
||||
networks:
|
||||
default:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue