2017-07-06 14:28:13 +00:00
package integration
2015-09-27 13:59:51 +00:00
import (
2022-06-27 13:16:08 +00:00
"bufio"
2019-01-15 13:28:04 +00:00
"bytes"
2020-03-05 17:03:08 +00:00
"crypto/rand"
2019-01-15 13:28:04 +00:00
"encoding/json"
2017-05-17 13:22:44 +00:00
"fmt"
2021-03-04 19:08:03 +00:00
"io"
2021-11-25 10:10:06 +00:00
"net"
2015-09-27 13:59:51 +00:00
"net/http"
2018-08-24 14:20:03 +00:00
"net/http/httptest"
2017-09-26 08:22:03 +00:00
"os"
2022-12-05 10:30:05 +00:00
"regexp"
2017-05-17 13:22:44 +00:00
"strings"
2019-08-26 17:00:04 +00:00
"sync/atomic"
2017-09-26 08:22:03 +00:00
"syscall"
2015-09-27 13:59:51 +00:00
"time"
2016-04-02 10:40:21 +00:00
"github.com/go-check/check"
2023-02-03 14:24:05 +00:00
"github.com/traefik/traefik/v3/integration/try"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
2015-09-27 13:59:51 +00:00
checker "github.com/vdemeester/shakers"
)
2020-05-11 10:06:07 +00:00
// SimpleSuite tests suite.
2015-11-03 22:06:31 +00:00
type SimpleSuite struct { BaseSuite }
2015-09-27 13:59:51 +00:00
func ( s * SimpleSuite ) TestInvalidConfigShouldFail ( c * check . C ) {
2017-07-10 12:58:31 +00:00
cmd , output := s . cmdTraefik ( withConfigFile ( "fixtures/invalid_configuration.toml" ) )
2016-04-19 17:23:08 +00:00
2017-05-17 13:22:44 +00:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2016-04-19 17:23:08 +00:00
2017-05-17 13:22:44 +00:00
err = try . Do ( 500 * time . Millisecond , func ( ) error {
2022-03-22 10:04:08 +00:00
expected := "expected '.' or '=', but got '{' instead"
2017-07-10 12:58:31 +00:00
actual := output . String ( )
2017-05-17 13:22:44 +00:00
if ! strings . Contains ( actual , expected ) {
2018-07-03 08:02:03 +00:00
return fmt . Errorf ( "got %s, wanted %s" , actual , expected )
2017-05-17 13:22:44 +00:00
}
return nil
} )
c . Assert ( err , checker . IsNil )
2015-09-27 13:59:51 +00:00
}
func ( s * SimpleSuite ) TestSimpleDefaultConfig ( c * check . C ) {
2017-07-10 12:58:31 +00:00
cmd , _ := s . cmdTraefik ( withConfigFile ( "fixtures/simple_default.toml" ) )
2017-05-17 13:22:44 +00:00
2015-09-27 13:59:51 +00:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2015-09-27 13:59:51 +00:00
2016-03-15 17:57:56 +00:00
// Expected a 404 as we did not configure anything
2017-05-17 13:22:44 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
2016-03-15 17:57:56 +00:00
c . Assert ( err , checker . IsNil )
2015-11-03 22:06:31 +00:00
}
func ( s * SimpleSuite ) TestWithWebConfig ( c * check . C ) {
2017-07-10 12:58:31 +00:00
cmd , _ := s . cmdTraefik ( withConfigFile ( "fixtures/simple_web.toml" ) )
2017-05-17 13:22:44 +00:00
2015-11-03 22:06:31 +00:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2015-11-03 22:06:31 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
2015-11-03 22:06:31 +00:00
c . Assert ( err , checker . IsNil )
2015-09-27 13:59:51 +00:00
}
2016-06-02 13:17:04 +00:00
func ( s * SimpleSuite ) TestPrintHelp ( c * check . C ) {
2017-07-10 12:58:31 +00:00
cmd , output := s . cmdTraefik ( "--help" )
2016-06-02 13:17:04 +00:00
2017-05-17 13:22:44 +00:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2016-06-02 13:17:04 +00:00
2017-05-17 13:22:44 +00:00
err = try . Do ( 500 * time . Millisecond , func ( ) error {
expected := "Usage:"
notExpected := "panic:"
2017-07-10 12:58:31 +00:00
actual := output . String ( )
2017-05-17 13:22:44 +00:00
if strings . Contains ( actual , notExpected ) {
2018-07-03 08:02:03 +00:00
return fmt . Errorf ( "got %s" , actual )
2017-05-17 13:22:44 +00:00
}
if ! strings . Contains ( actual , expected ) {
2018-07-03 08:02:03 +00:00
return fmt . Errorf ( "got %s, wanted %s" , actual , expected )
2017-05-17 13:22:44 +00:00
}
return nil
} )
c . Assert ( err , checker . IsNil )
2016-06-02 13:17:04 +00:00
}
2017-09-26 08:22:03 +00:00
func ( s * SimpleSuite ) TestRequestAcceptGraceTimeout ( c * check . C ) {
s . createComposeProject ( c , "reqacceptgrace" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
whoamiURL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami" ) , "80" )
2017-09-26 08:22:03 +00:00
file := s . adaptFile ( c , "fixtures/reqacceptgrace.toml" , struct {
Server string
2021-11-25 10:10:06 +00:00
} { whoamiURL } )
2017-09-26 08:22:03 +00:00
defer os . Remove ( file )
2019-07-15 08:22:03 +00:00
2017-09-26 08:22:03 +00:00
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
2021-11-25 10:10:06 +00:00
2017-09-26 08:22:03 +00:00
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2017-09-26 08:22:03 +00:00
// Wait for Traefik to turn ready.
err = try . GetRequest ( "http://127.0.0.1:8000/" , 2 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
// Make sure exposed service is ready.
err = try . GetRequest ( "http://127.0.0.1:8000/service" , 3 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2018-03-22 17:18:03 +00:00
// Check that /ping endpoint is responding with 200.
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 3 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2017-09-26 08:22:03 +00:00
// Send SIGTERM to Traefik.
proc , err := os . FindProcess ( cmd . Process . Pid )
c . Assert ( err , checker . IsNil )
err = proc . Signal ( syscall . SIGTERM )
c . Assert ( err , checker . IsNil )
// Give Traefik time to process the SIGTERM and send a request half-way
// into the request accepting grace period, by which requests should
// still get served.
time . Sleep ( 5 * time . Second )
resp , err := http . Get ( "http://127.0.0.1:8000/service" )
c . Assert ( err , checker . IsNil )
defer resp . Body . Close ( )
c . Assert ( resp . StatusCode , checker . Equals , http . StatusOK )
2018-03-22 17:18:03 +00:00
// ping endpoint should now return a Service Unavailable.
resp , err = http . Get ( "http://127.0.0.1:8001/ping" )
c . Assert ( err , checker . IsNil )
defer resp . Body . Close ( )
c . Assert ( resp . StatusCode , checker . Equals , http . StatusServiceUnavailable )
2017-09-26 08:22:03 +00:00
// Expect Traefik to shut down gracefully once the request accepting grace
// period has elapsed.
waitErr := make ( chan error )
go func ( ) {
waitErr <- cmd . Wait ( )
} ( )
select {
case err := <- waitErr :
c . Assert ( err , checker . IsNil )
case <- time . After ( 10 * time . Second ) :
// By now we are ~5 seconds out of the request accepting grace period
// (start + 5 seconds sleep prior to the mid-grace period request +
// 10 seconds timeout = 15 seconds > 10 seconds grace period).
// Something must have gone wrong if we still haven't terminated at
// this point.
c . Fatal ( "Traefik did not terminate in time" )
}
}
2017-11-09 15:12:04 +00:00
2020-07-01 12:40:04 +00:00
func ( s * SimpleSuite ) TestCustomPingTerminationStatusCode ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/custom_ping_termination_status_code.toml" , struct { } { } )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-07-01 12:40:04 +00:00
// Wait for Traefik to turn ready.
err = try . GetRequest ( "http://127.0.0.1:8001/" , 2 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
// Check that /ping endpoint is responding with 200.
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 3 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
// Send SIGTERM to Traefik.
proc , err := os . FindProcess ( cmd . Process . Pid )
c . Assert ( err , checker . IsNil )
err = proc . Signal ( syscall . SIGTERM )
c . Assert ( err , checker . IsNil )
// ping endpoint should now return a Service Unavailable.
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 2 * time . Second , try . StatusCodeIs ( http . StatusNoContent ) )
c . Assert ( err , checker . IsNil )
}
2017-11-30 11:18:03 +00:00
func ( s * SimpleSuite ) TestStatsWithMultipleEntryPoint ( c * check . C ) {
2019-01-18 14:18:04 +00:00
c . Skip ( "Stats is missing" )
2017-11-30 11:18:03 +00:00
s . createComposeProject ( c , "stats" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
whoami1URL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami1" ) , "80" )
whoami2URL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami2" ) , "80" )
2017-11-30 11:18:03 +00:00
file := s . adaptFile ( c , "fixtures/simple_stats.toml" , struct {
Server1 string
Server2 string
2021-11-25 10:10:06 +00:00
} { whoami1URL , whoami2URL } )
2017-11-30 11:18:03 +00:00
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2017-11-30 11:18:03 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
2017-11-30 11:18:03 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/health" , 1 * time . Second , try . BodyContains ( ` "total_status_code_count": { "200":2} ` ) )
c . Assert ( err , checker . IsNil )
}
2017-11-09 15:12:04 +00:00
func ( s * SimpleSuite ) TestNoAuthOnPing ( c * check . C ) {
2019-07-19 10:28:07 +00:00
c . Skip ( "Waiting for new api handler implementation" )
2017-11-09 15:12:04 +00:00
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2017-11-09 15:12:04 +00:00
2019-07-15 08:22:03 +00:00
file := s . adaptFile ( c , "./fixtures/simple_auth.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
2017-11-09 15:12:04 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2017-11-09 15:12:04 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8001/api/rawdata" , 2 * time . Second , try . StatusCodeIs ( http . StatusUnauthorized ) )
2017-11-09 15:12:04 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8001/ping" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2019-07-15 08:22:03 +00:00
func ( s * SimpleSuite ) TestDefaultEntryPointHTTP ( c * check . C ) {
2017-11-30 15:10:02 +00:00
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2017-11-30 15:10:02 +00:00
2019-09-06 13:08:04 +00:00
cmd , output := s . traefikCmd ( "--entryPoints.http.Address=:8000" , "--log.level=DEBUG" , "--providers.docker" , "--api.insecure" )
2017-11-30 15:10:02 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2017-11-30 15:10:02 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
2017-11-30 15:10:02 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2019-07-15 08:22:03 +00:00
func ( s * SimpleSuite ) TestWithNonExistingEntryPoint ( c * check . C ) {
2017-11-30 15:10:02 +00:00
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2017-11-30 15:10:02 +00:00
2019-09-06 13:08:04 +00:00
cmd , output := s . traefikCmd ( "--entryPoints.http.Address=:8000" , "--log.level=DEBUG" , "--providers.docker" , "--api.insecure" )
2017-11-30 15:10:02 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2017-11-30 15:10:02 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
2017-11-30 15:10:02 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
}
2018-01-19 13:30:04 +00:00
2019-07-15 08:22:03 +00:00
func ( s * SimpleSuite ) TestMetricsPrometheusDefaultEntryPoint ( c * check . C ) {
2018-01-19 13:30:04 +00:00
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2018-01-19 13:30:04 +00:00
2021-04-30 08:22:04 +00:00
cmd , output := s . traefikCmd ( "--entryPoints.http.Address=:8000" , "--api.insecure" , "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0" , "--providers.docker" , "--metrics.prometheus.addrouterslabels=true" , "--log.level=DEBUG" )
2018-01-19 13:30:04 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2018-01-19 13:30:04 +00:00
2022-10-27 14:08:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix(`/whoami`)" ) )
2018-01-19 13:30:04 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/metrics" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2021-04-30 08:22:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/metrics" , 1 * time . Second , try . BodyContains ( "_router_" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/metrics" , 1 * time . Second , try . BodyContains ( "_entrypoint_" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/metrics" , 1 * time . Second , try . BodyContains ( "_service_" ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestMetricsPrometheusTwoRoutersOneService ( c * check . C ) {
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2021-04-30 08:22:04 +00:00
cmd , output := s . traefikCmd ( "--entryPoints.http.Address=:8000" , "--api.insecure" , "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0" , "--providers.docker" , "--metrics.prometheus.addentrypointslabels=false" , "--metrics.prometheus.addrouterslabels=true" , "--log.level=DEBUG" )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/whoami2" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2021-09-15 15:26:06 +00:00
// adding a loop to test if metrics are not deleted
for i := 0 ; i < 10 ; i ++ {
request , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8080/metrics" , nil )
c . Assert ( err , checker . IsNil )
2021-04-30 08:22:04 +00:00
2021-09-15 15:26:06 +00:00
response , err := http . DefaultClient . Do ( request )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
2021-04-30 08:22:04 +00:00
2021-09-15 15:26:06 +00:00
body , err := io . ReadAll ( response . Body )
c . Assert ( err , checker . IsNil )
2021-04-30 08:22:04 +00:00
2021-09-15 15:26:06 +00:00
// Reqs count of 1 for both routers
2021-11-25 10:10:06 +00:00
c . Assert ( string ( body ) , checker . Contains , "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-traefik-integration-test-base@docker\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-traefik-integration-test-base@docker\"} 1" )
2021-09-15 15:26:06 +00:00
// Reqs count of 2 for service behind both routers
2021-11-25 10:10:06 +00:00
c . Assert ( string ( body ) , checker . Contains , "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-traefik-integration-test-base@docker\"} 2" )
2021-09-15 15:26:06 +00:00
}
2018-01-19 13:30:04 +00:00
}
2018-02-16 10:04:04 +00:00
2022-10-27 14:08:06 +00:00
// TestMetricsWithBufferingMiddleware checks that the buffering middleware
// (which introduces its own response writer in the chain), does not interfere with
// the capture middleware on which the metrics mechanism relies.
func ( s * SimpleSuite ) TestMetricsWithBufferingMiddleware ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeUp ( c )
defer s . composeDown ( c )
server := httptest . NewUnstartedServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
w . WriteHeader ( http . StatusOK )
_ , _ = w . Write ( [ ] byte ( "MORE THAN TEN BYTES IN RESPONSE" ) )
} ) )
server . Start ( )
defer server . Close ( )
file := s . adaptFile ( c , "fixtures/simple_metrics_with_buffer_middleware.toml" , struct { IP string } { IP : strings . TrimPrefix ( server . URL , "http://" ) } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix(`/without`)" ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8001/without" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8002/with-req" , strings . NewReader ( "MORE THAN TEN BYTES IN REQUEST" ) )
c . Assert ( err , checker . IsNil )
// The request should fail because the body is too large.
err = try . Request ( req , 1 * time . Second , try . StatusCodeIs ( http . StatusRequestEntityTooLarge ) )
c . Assert ( err , checker . IsNil )
// The request should fail because the response exceeds the configured limit.
err = try . GetRequest ( "http://127.0.0.1:8003/with-resp" , 1 * time . Second , try . StatusCodeIs ( http . StatusInternalServerError ) )
c . Assert ( err , checker . IsNil )
request , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8080/metrics" , nil )
c . Assert ( err , checker . IsNil )
response , err := http . DefaultClient . Do ( request )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
body , err := io . ReadAll ( response . Body )
c . Assert ( err , checker . IsNil )
// For allowed requests and responses, the entrypoint and service metrics have the same status code.
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_bytes_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 0" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_responses_bytes_total{code=\"200\",entrypoint=\"webA\",method=\"GET\",protocol=\"http\"} 31" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_requests_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 0" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_responses_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-without@file\"} 31" )
// For forbidden requests, the entrypoints have metrics, the services don't.
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_bytes_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 0" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_responses_bytes_total{code=\"413\",entrypoint=\"webB\",method=\"GET\",protocol=\"http\"} 24" )
// For disallowed responses, the entrypoint and service metrics don't have the same status code.
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_bytes_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 0" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_requests_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_entrypoint_responses_bytes_total{code=\"500\",entrypoint=\"webC\",method=\"GET\",protocol=\"http\"} 21" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_requests_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 0" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 1" )
c . Assert ( string ( body ) , checker . Contains , "traefik_service_responses_bytes_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"service-resp@file\"} 31" )
}
2018-02-16 10:04:04 +00:00
func ( s * SimpleSuite ) TestMultipleProviderSameBackendName ( c * check . C ) {
s . createComposeProject ( c , "base" )
2018-08-24 14:20:03 +00:00
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
whoami1IP := s . getComposeServiceIP ( c , "whoami1" )
whoami2IP := s . getComposeServiceIP ( c , "whoami2" )
file := s . adaptFile ( c , "fixtures/multiple_provider.toml" , struct { IP string } { IP : whoami2IP } )
2018-02-16 10:04:04 +00:00
defer os . Remove ( file )
2018-08-24 14:20:03 +00:00
2018-02-16 10:04:04 +00:00
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2018-02-16 10:04:04 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix" ) )
2018-02-16 10:04:04 +00:00
c . Assert ( err , checker . IsNil )
2021-11-25 10:10:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/whoami" , 1 * time . Second , try . BodyContains ( whoami1IP ) )
2018-02-16 10:04:04 +00:00
c . Assert ( err , checker . IsNil )
2021-11-25 10:10:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/file" , 1 * time . Second , try . BodyContains ( whoami2IP ) )
2018-02-16 10:04:04 +00:00
c . Assert ( err , checker . IsNil )
}
2018-08-24 14:20:03 +00:00
2022-10-26 15:16:05 +00:00
func ( s * SimpleSuite ) TestIPStrategyAllowlist ( c * check . C ) {
s . createComposeProject ( c , "allowlist" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2018-08-24 14:20:03 +00:00
2022-10-26 15:16:05 +00:00
cmd , output := s . traefikCmd ( withConfigFile ( "fixtures/simple_allowlist.toml" ) )
2018-08-24 14:20:03 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2018-08-24 14:20:03 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 2 * time . Second , try . BodyContains ( "override" ) )
2019-01-18 14:18:04 +00:00
c . Assert ( err , checker . IsNil )
2022-10-26 15:16:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 2 * time . Second , try . BodyContains ( "override.remoteaddr.allowlist.docker.local" ) )
2018-08-24 14:20:03 +00:00
c . Assert ( err , checker . IsNil )
testCases := [ ] struct {
desc string
xForwardedFor string
host string
expectedStatusCode int
} {
{
desc : "override remote addr reject" ,
xForwardedFor : "8.8.8.8,8.8.8.8" ,
2022-10-26 15:16:05 +00:00
host : "override.remoteaddr.allowlist.docker.local" ,
2018-08-24 14:20:03 +00:00
expectedStatusCode : 403 ,
} ,
{
desc : "override depth accept" ,
xForwardedFor : "8.8.8.8,10.0.0.1,127.0.0.1" ,
2022-10-26 15:16:05 +00:00
host : "override.depth.allowlist.docker.local" ,
2018-08-24 14:20:03 +00:00
expectedStatusCode : 200 ,
} ,
{
desc : "override depth reject" ,
xForwardedFor : "10.0.0.1,8.8.8.8,127.0.0.1" ,
2022-10-26 15:16:05 +00:00
host : "override.depth.allowlist.docker.local" ,
2018-08-24 14:20:03 +00:00
expectedStatusCode : 403 ,
} ,
{
desc : "override excludedIPs reject" ,
xForwardedFor : "10.0.0.3,10.0.0.1,10.0.0.2" ,
2022-10-26 15:16:05 +00:00
host : "override.excludedips.allowlist.docker.local" ,
2018-08-24 14:20:03 +00:00
expectedStatusCode : 403 ,
} ,
{
desc : "override excludedIPs accept" ,
xForwardedFor : "8.8.8.8,10.0.0.1,10.0.0.2" ,
2022-10-26 15:16:05 +00:00
host : "override.excludedips.allowlist.docker.local" ,
2018-08-24 14:20:03 +00:00
expectedStatusCode : 200 ,
} ,
}
for _ , test := range testCases {
req := httptest . NewRequest ( http . MethodGet , "http://127.0.0.1:8000" , nil )
req . Header . Set ( "X-Forwarded-For" , test . xForwardedFor )
req . Host = test . host
req . RequestURI = ""
err = try . Request ( req , 1 * time . Second , try . StatusCodeIs ( test . expectedStatusCode ) )
if err != nil {
c . Fatalf ( "Error while %s: %v" , test . desc , err )
}
}
}
2018-10-30 11:34:00 +00:00
2019-04-02 14:56:05 +00:00
func ( s * SimpleSuite ) TestXForwardedHeaders ( c * check . C ) {
2022-10-26 15:16:05 +00:00
s . createComposeProject ( c , "allowlist" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2019-04-02 14:56:05 +00:00
2022-10-26 15:16:05 +00:00
cmd , output := s . traefikCmd ( withConfigFile ( "fixtures/simple_allowlist.toml" ) )
2019-04-02 14:56:05 +00:00
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-04-02 14:56:05 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 2 * time . Second ,
2022-10-26 15:16:05 +00:00
try . BodyContains ( "override.remoteaddr.allowlist.docker.local" ) )
2019-04-02 14:56:05 +00:00
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000" , nil )
c . Assert ( err , checker . IsNil )
2022-10-26 15:16:05 +00:00
req . Host = "override.depth.allowlist.docker.local"
2019-04-02 14:56:05 +00:00
req . Header . Set ( "X-Forwarded-For" , "8.8.8.8,10.0.0.1,127.0.0.1" )
err = try . Request ( req , 1 * time . Second ,
try . StatusCodeIs ( http . StatusOK ) ,
try . BodyContains ( "X-Forwarded-Proto" , "X-Forwarded-For" , "X-Forwarded-Host" ,
"X-Forwarded-Host" , "X-Forwarded-Port" , "X-Forwarded-Server" , "X-Real-Ip" ) )
c . Assert ( err , checker . IsNil )
}
2019-07-15 08:22:03 +00:00
func ( s * SimpleSuite ) TestMultiProvider ( c * check . C ) {
2019-01-15 13:28:04 +00:00
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2019-01-15 13:28:04 +00:00
2021-11-25 10:10:06 +00:00
whoamiURL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami1" ) , "80" )
file := s . adaptFile ( c , "fixtures/multiprovider.toml" , struct { Server string } { Server : whoamiURL } )
2019-01-15 13:28:04 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-01-15 13:28:04 +00:00
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1000 * time . Millisecond , try . BodyContains ( "service" ) )
2019-01-15 13:28:04 +00:00
c . Assert ( err , checker . IsNil )
2019-07-12 23:24:03 +00:00
config := dynamic . Configuration {
HTTP : & dynamic . HTTPConfiguration {
Routers : map [ string ] * dynamic . Router {
"router1" : {
EntryPoints : [ ] string { "web" } ,
Middlewares : [ ] string { "customheader@file" } ,
Service : "service@file" ,
Rule : "PathPrefix(`/`)" ,
} ,
2019-01-15 13:28:04 +00:00
} ,
} ,
}
2019-07-15 08:22:03 +00:00
jsonContent , err := json . Marshal ( config )
2019-01-15 13:28:04 +00:00
c . Assert ( err , checker . IsNil )
2019-07-15 08:22:03 +00:00
request , err := http . NewRequest ( http . MethodPut , "http://127.0.0.1:8080/api/providers/rest" , bytes . NewReader ( jsonContent ) )
2019-01-15 13:28:04 +00:00
c . Assert ( err , checker . IsNil )
response , err := http . DefaultClient . Do ( request )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
2019-05-16 08:58:06 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1000 * time . Millisecond , try . BodyContains ( "PathPrefix(`/`)" ) )
2019-01-15 13:28:04 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) , try . BodyContains ( "CustomValue" ) )
c . Assert ( err , checker . IsNil )
}
2019-05-06 15:16:03 +00:00
func ( s * SimpleSuite ) TestSimpleConfigurationHostRequestTrailingPeriod ( c * check . C ) {
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2019-05-06 15:16:03 +00:00
2021-11-25 10:10:06 +00:00
whoamiURL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami1" ) , "80" )
file := s . adaptFile ( c , "fixtures/file/simple-hosts.toml" , struct { Server string } { Server : whoamiURL } )
2019-05-06 15:16:03 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-05-06 15:16:03 +00:00
testCases := [ ] struct {
desc string
requestHost string
} {
{
desc : "Request host without trailing period, rule without trailing period" ,
requestHost : "test.localhost" ,
} ,
{
desc : "Request host with trailing period, rule without trailing period" ,
requestHost : "test.localhost." ,
} ,
{
desc : "Request host without trailing period, rule with trailing period" ,
requestHost : "test.foo.localhost" ,
} ,
{
desc : "Request host with trailing period, rule with trailing period" ,
requestHost : "test.foo.localhost." ,
} ,
}
for _ , test := range testCases {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000" , nil )
c . Assert ( err , checker . IsNil )
req . Host = test . requestHost
err = try . Request ( req , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
if err != nil {
c . Fatalf ( "Error while testing %s: %v" , test . desc , err )
}
}
}
2019-07-15 15:04:04 +00:00
func ( s * SimpleSuite ) TestRouterConfigErrors ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/router_errors.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-07-15 15:04:04 +00:00
// All errors
2019-07-19 09:52:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/routers" , 1000 * time . Millisecond , try . BodyContains ( ` ["middleware \"unknown@file\" does not exist","found different TLS options for routers on the same host snitest.net, so using the default TLS options instead"] ` ) )
2019-07-15 15:04:04 +00:00
c . Assert ( err , checker . IsNil )
2019-08-29 10:38:04 +00:00
// router3 has an error because it uses an unknown entrypoint
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/routers/router3@file" , 1000 * time . Millisecond , try . BodyContains ( ` entryPoint \"unknown-entrypoint\" doesn't exist ` , "no valid entryPoint for this router" ) )
c . Assert ( err , checker . IsNil )
2019-07-15 15:04:04 +00:00
// router4 is enabled, but in warning state because its tls options conf was messed up
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/routers/router4@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"warning" ` ) )
c . Assert ( err , checker . IsNil )
// router5 is disabled because its middleware conf is broken
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/routers/router5@file" , 1000 * time . Millisecond , try . BodyContains ( ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestServiceConfigErrors ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/service_errors.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-07-15 15:04:04 +00:00
2019-08-26 08:30:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( ` ["the service \"service1@file\" does not have any type defined"] ` ) )
2019-07-15 15:04:04 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services/service1@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"disabled" ` ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services/service2@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"enabled" ` ) )
c . Assert ( err , checker . IsNil )
}
2019-08-26 08:30:05 +00:00
2020-02-11 00:26:04 +00:00
func ( s * SimpleSuite ) TestTCPRouterConfigErrors ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/router_errors.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-02-11 00:26:04 +00:00
// router3 has an error because it uses an unknown entrypoint
err = try . GetRequest ( "http://127.0.0.1:8080/api/tcp/routers/router3@file" , 1000 * time . Millisecond , try . BodyContains ( ` entryPoint \"unknown-entrypoint\" doesn't exist ` , "no valid entryPoint for this router" ) )
c . Assert ( err , checker . IsNil )
// router4 has an unsupported Rule
2022-03-17 17:02:08 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/tcp/routers/router4@file" , 1000 * time . Millisecond , try . BodyContains ( "invalid rule: \\\"Host(`mydomain.com`)\\\"" ) )
2020-02-11 00:26:04 +00:00
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestTCPServiceConfigErrors ( c * check . C ) {
2020-02-17 17:02:04 +00:00
file := s . adaptFile ( c , "fixtures/tcp/service_errors.toml" , struct { } { } )
2020-02-11 00:26:04 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-02-11 00:26:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/tcp/services" , 1000 * time . Millisecond , try . BodyContains ( ` ["the service \"service1@file\" does not have any type defined"] ` ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/tcp/services/service1@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"disabled" ` ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/tcp/services/service2@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"enabled" ` ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestUDPRouterConfigErrors ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/router_errors.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-02-11 00:26:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/udp/routers/router3@file" , 1000 * time . Millisecond , try . BodyContains ( ` entryPoint \"unknown-entrypoint\" doesn't exist ` , "no valid entryPoint for this router" ) )
c . Assert ( err , checker . IsNil )
}
func ( s * SimpleSuite ) TestUDPServiceConfigErrors ( c * check . C ) {
2020-02-17 17:02:04 +00:00
file := s . adaptFile ( c , "fixtures/udp/service_errors.toml" , struct { } { } )
2020-02-11 00:26:04 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-02-11 00:26:04 +00:00
2022-11-21 17:36:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/udp/services" , 1000 * time . Millisecond , try . BodyContains ( ` ["the UDP service \"service1@file\" does not have any type defined"] ` ) )
2020-02-11 00:26:04 +00:00
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/udp/services/service1@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"disabled" ` ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/udp/services/service2@file" , 1000 * time . Millisecond , try . BodyContains ( ` "status":"enabled" ` ) )
c . Assert ( err , checker . IsNil )
}
2019-08-26 08:30:05 +00:00
func ( s * SimpleSuite ) TestWRR ( c * check . C ) {
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
whoami1IP := s . getComposeServiceIP ( c , "whoami1" )
whoami2IP := s . getComposeServiceIP ( c , "whoami2" )
2019-08-26 08:30:05 +00:00
file := s . adaptFile ( c , "fixtures/wrr.toml" , struct {
Server1 string
Server2 string
2021-11-25 10:10:06 +00:00
} { Server1 : "http://" + whoami1IP , Server2 : "http://" + whoami2IP } )
2019-08-26 08:30:05 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-08-26 08:30:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( "service1" , "service2" ) )
c . Assert ( err , checker . IsNil )
repartition := map [ string ] int { }
for i := 0 ; i < 4 ; i ++ {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoami" , nil )
c . Assert ( err , checker . IsNil )
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
2021-03-04 19:08:03 +00:00
body , err := io . ReadAll ( response . Body )
2019-08-26 08:30:05 +00:00
c . Assert ( err , checker . IsNil )
2021-11-25 10:10:06 +00:00
if strings . Contains ( string ( body ) , whoami1IP ) {
repartition [ whoami1IP ] ++
2019-08-26 08:30:05 +00:00
}
2021-11-25 10:10:06 +00:00
if strings . Contains ( string ( body ) , whoami2IP ) {
repartition [ whoami2IP ] ++
2019-08-26 08:30:05 +00:00
}
}
2021-11-25 10:10:06 +00:00
c . Assert ( repartition [ whoami1IP ] , checker . Equals , 3 )
c . Assert ( repartition [ whoami2IP ] , checker . Equals , 1 )
2019-08-26 08:30:05 +00:00
}
func ( s * SimpleSuite ) TestWRRSticky ( c * check . C ) {
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
whoami1IP := s . getComposeServiceIP ( c , "whoami1" )
whoami2IP := s . getComposeServiceIP ( c , "whoami2" )
2019-08-26 08:30:05 +00:00
file := s . adaptFile ( c , "fixtures/wrr_sticky.toml" , struct {
Server1 string
Server2 string
2021-11-25 10:10:06 +00:00
} { Server1 : "http://" + whoami1IP , Server2 : "http://" + whoami2IP } )
2019-08-26 08:30:05 +00:00
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-08-26 08:30:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( "service1" , "service2" ) )
c . Assert ( err , checker . IsNil )
repartition := map [ string ] int { }
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoami" , nil )
c . Assert ( err , checker . IsNil )
2019-09-26 09:00:06 +00:00
for i := 0 ; i < 4 ; i ++ {
2019-08-26 08:30:05 +00:00
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
for _ , cookie := range response . Cookies ( ) {
req . AddCookie ( cookie )
}
2021-03-04 19:08:03 +00:00
body , err := io . ReadAll ( response . Body )
2019-08-26 08:30:05 +00:00
c . Assert ( err , checker . IsNil )
2021-11-25 10:10:06 +00:00
if strings . Contains ( string ( body ) , whoami1IP ) {
repartition [ whoami1IP ] ++
2019-08-26 08:30:05 +00:00
}
2021-11-25 10:10:06 +00:00
if strings . Contains ( string ( body ) , whoami2IP ) {
repartition [ whoami2IP ] ++
2019-08-26 08:30:05 +00:00
}
}
2021-11-25 10:10:06 +00:00
c . Assert ( repartition [ whoami1IP ] , checker . Equals , 4 )
c . Assert ( repartition [ whoami2IP ] , checker . Equals , 0 )
2019-08-26 08:30:05 +00:00
}
2019-08-26 17:00:04 +00:00
func ( s * SimpleSuite ) TestMirror ( c * check . C ) {
var count , countMirror1 , countMirror2 int32
main := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & count , 1 )
} ) )
mirror1 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & countMirror1 , 1 )
} ) )
mirror2 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & countMirror2 , 1 )
} ) )
mainServer := main . URL
mirror1Server := mirror1 . URL
mirror2Server := mirror2 . URL
file := s . adaptFile ( c , "fixtures/mirror.toml" , struct {
MainServer string
Mirror1Server string
Mirror2Server string
} { MainServer : mainServer , Mirror1Server : mirror1Server , Mirror2Server : mirror2Server } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-08-26 17:00:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( "mirror1" , "mirror2" , "service1" ) )
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoami" , nil )
c . Assert ( err , checker . IsNil )
for i := 0 ; i < 10 ; i ++ {
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
}
countTotal := atomic . LoadInt32 ( & count )
val1 := atomic . LoadInt32 ( & countMirror1 )
val2 := atomic . LoadInt32 ( & countMirror2 )
c . Assert ( countTotal , checker . Equals , int32 ( 10 ) )
c . Assert ( val1 , checker . Equals , int32 ( 1 ) )
c . Assert ( val2 , checker . Equals , int32 ( 5 ) )
}
2020-03-05 17:03:08 +00:00
func ( s * SimpleSuite ) TestMirrorWithBody ( c * check . C ) {
var count , countMirror1 , countMirror2 int32
body20 := make ( [ ] byte , 20 )
_ , err := rand . Read ( body20 )
c . Assert ( err , checker . IsNil )
body5 := make ( [ ] byte , 5 )
_ , err = rand . Read ( body5 )
c . Assert ( err , checker . IsNil )
verifyBody := func ( req * http . Request ) {
2021-03-04 19:08:03 +00:00
b , _ := io . ReadAll ( req . Body )
2020-03-05 17:03:08 +00:00
switch req . Header . Get ( "Size" ) {
case "20" :
if ! bytes . Equal ( b , body20 ) {
c . Fatalf ( "Not Equals \n%v \n%v" , body20 , b )
}
case "5" :
if ! bytes . Equal ( b , body5 ) {
c . Fatalf ( "Not Equals \n%v \n%v" , body5 , b )
}
default :
c . Fatal ( "Size header not present" )
}
}
main := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
verifyBody ( req )
atomic . AddInt32 ( & count , 1 )
} ) )
mirror1 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
verifyBody ( req )
atomic . AddInt32 ( & countMirror1 , 1 )
} ) )
mirror2 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
verifyBody ( req )
atomic . AddInt32 ( & countMirror2 , 1 )
} ) )
mainServer := main . URL
mirror1Server := mirror1 . URL
mirror2Server := mirror2 . URL
file := s . adaptFile ( c , "fixtures/mirror.toml" , struct {
MainServer string
Mirror1Server string
Mirror2Server string
} { MainServer : mainServer , Mirror1Server : mirror1Server , Mirror2Server : mirror2Server } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err = cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-03-05 17:03:08 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( "mirror1" , "mirror2" , "service1" ) )
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoami" , bytes . NewBuffer ( body20 ) )
c . Assert ( err , checker . IsNil )
req . Header . Set ( "Size" , "20" )
for i := 0 ; i < 10 ; i ++ {
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
}
countTotal := atomic . LoadInt32 ( & count )
val1 := atomic . LoadInt32 ( & countMirror1 )
val2 := atomic . LoadInt32 ( & countMirror2 )
c . Assert ( countTotal , checker . Equals , int32 ( 10 ) )
c . Assert ( val1 , checker . Equals , int32 ( 1 ) )
c . Assert ( val2 , checker . Equals , int32 ( 5 ) )
atomic . StoreInt32 ( & count , 0 )
atomic . StoreInt32 ( & countMirror1 , 0 )
atomic . StoreInt32 ( & countMirror2 , 0 )
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoamiWithMaxBody" , bytes . NewBuffer ( body5 ) )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
req . Header . Set ( "Size" , "5" )
2020-03-05 17:03:08 +00:00
for i := 0 ; i < 10 ; i ++ {
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
}
countTotal = atomic . LoadInt32 ( & count )
val1 = atomic . LoadInt32 ( & countMirror1 )
val2 = atomic . LoadInt32 ( & countMirror2 )
c . Assert ( countTotal , checker . Equals , int32 ( 10 ) )
c . Assert ( val1 , checker . Equals , int32 ( 1 ) )
c . Assert ( val2 , checker . Equals , int32 ( 5 ) )
atomic . StoreInt32 ( & count , 0 )
atomic . StoreInt32 ( & countMirror1 , 0 )
atomic . StoreInt32 ( & countMirror2 , 0 )
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoamiWithMaxBody" , bytes . NewBuffer ( body20 ) )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
req . Header . Set ( "Size" , "20" )
2020-03-05 17:03:08 +00:00
for i := 0 ; i < 10 ; i ++ {
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
}
countTotal = atomic . LoadInt32 ( & count )
val1 = atomic . LoadInt32 ( & countMirror1 )
val2 = atomic . LoadInt32 ( & countMirror2 )
c . Assert ( countTotal , checker . Equals , int32 ( 10 ) )
c . Assert ( val1 , checker . Equals , int32 ( 0 ) )
c . Assert ( val2 , checker . Equals , int32 ( 0 ) )
}
2019-08-26 17:00:04 +00:00
func ( s * SimpleSuite ) TestMirrorCanceled ( c * check . C ) {
var count , countMirror1 , countMirror2 int32
main := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & count , 1 )
2019-11-26 20:38:03 +00:00
time . Sleep ( 2 * time . Second )
2019-08-26 17:00:04 +00:00
} ) )
mirror1 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & countMirror1 , 1 )
} ) )
mirror2 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
atomic . AddInt32 ( & countMirror2 , 1 )
} ) )
mainServer := main . URL
mirror1Server := mirror1 . URL
mirror2Server := mirror2 . URL
file := s . adaptFile ( c , "fixtures/mirror.toml" , struct {
MainServer string
Mirror1Server string
Mirror2Server string
} { MainServer : mainServer , Mirror1Server : mirror1Server , Mirror2Server : mirror2Server } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-08-26 17:00:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8080/api/http/services" , 1000 * time . Millisecond , try . BodyContains ( "mirror1" , "mirror2" , "service1" ) )
c . Assert ( err , checker . IsNil )
for i := 0 ; i < 5 ; i ++ {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/whoami" , nil )
c . Assert ( err , checker . IsNil )
2019-09-10 15:52:04 +00:00
client := & http . Client {
Timeout : time . Second ,
}
_ , _ = client . Do ( req )
2019-08-26 17:00:04 +00:00
}
countTotal := atomic . LoadInt32 ( & count )
val1 := atomic . LoadInt32 ( & countMirror1 )
val2 := atomic . LoadInt32 ( & countMirror2 )
c . Assert ( countTotal , checker . Equals , int32 ( 5 ) )
c . Assert ( val1 , checker . Equals , int32 ( 0 ) )
c . Assert ( val2 , checker . Equals , int32 ( 0 ) )
}
2019-09-06 13:08:04 +00:00
func ( s * SimpleSuite ) TestSecureAPI ( c * check . C ) {
s . createComposeProject ( c , "base" )
2021-11-25 10:10:06 +00:00
s . composeUp ( c )
defer s . composeDown ( c )
2019-09-06 13:08:04 +00:00
file := s . adaptFile ( c , "./fixtures/simple_secure_api.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2019-09-06 13:08:04 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/secure/api/rawdata" , 1 * time . Second , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/api/rawdata" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
}
2020-01-21 17:06:03 +00:00
func ( s * SimpleSuite ) TestContentTypeDisableAutoDetect ( c * check . C ) {
srv1 := httptest . NewServer ( http . HandlerFunc ( func ( rw http . ResponseWriter , req * http . Request ) {
rw . Header ( ) [ "Content-Type" ] = nil
2022-11-29 10:48:05 +00:00
path := strings . TrimPrefix ( req . URL . Path , "/autodetect" )
switch path [ : 4 ] {
2020-01-21 17:06:03 +00:00
case "/css" :
2022-11-29 10:48:05 +00:00
if strings . Contains ( req . URL . Path , "/ct" ) {
2020-01-21 17:06:03 +00:00
rw . Header ( ) . Set ( "Content-Type" , "text/css" )
}
rw . WriteHeader ( http . StatusOK )
_ , err := rw . Write ( [ ] byte ( ".testcss { }" ) )
c . Assert ( err , checker . IsNil )
case "/pdf" :
2022-11-29 10:48:05 +00:00
if strings . Contains ( req . URL . Path , "/ct" ) {
2020-01-21 17:06:03 +00:00
rw . Header ( ) . Set ( "Content-Type" , "application/pdf" )
}
rw . WriteHeader ( http . StatusOK )
2021-03-04 19:08:03 +00:00
data , err := os . ReadFile ( "fixtures/test.pdf" )
2020-01-21 17:06:03 +00:00
c . Assert ( err , checker . IsNil )
2020-10-09 07:32:03 +00:00
_ , err = rw . Write ( data )
2020-01-21 17:06:03 +00:00
c . Assert ( err , checker . IsNil )
}
} ) )
defer srv1 . Close ( )
file := s . adaptFile ( c , "fixtures/simple_contenttype.toml" , struct {
Server string
} {
Server : srv1 . URL ,
} )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) , "--log.level=DEBUG" )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , check . IsNil )
2020-10-09 07:32:03 +00:00
defer s . killCmd ( cmd )
2020-01-21 17:06:03 +00:00
// wait for traefik
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 10 * time . Second , try . BodyContains ( "127.0.0.1" ) )
c . Assert ( err , checker . IsNil )
2022-11-29 10:48:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/css/ct" , time . Second , try . HasHeaderValue ( "Content-Type" , "text/css" , false ) )
2020-01-21 17:06:03 +00:00
c . Assert ( err , checker . IsNil )
2022-11-29 10:48:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/pdf/ct" , time . Second , try . HasHeaderValue ( "Content-Type" , "application/pdf" , false ) )
2020-01-21 17:06:03 +00:00
c . Assert ( err , checker . IsNil )
2022-11-29 10:48:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/css/noct" , time . Second , func ( res * http . Response ) error {
2020-01-21 17:06:03 +00:00
if ct , ok := res . Header [ "Content-Type" ] ; ok {
return fmt . Errorf ( "should have no content type and %s is present" , ct )
}
return nil
} )
c . Assert ( err , checker . IsNil )
2022-11-29 10:48:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/pdf/noct" , time . Second , func ( res * http . Response ) error {
2020-01-21 17:06:03 +00:00
if ct , ok := res . Header [ "Content-Type" ] ; ok {
return fmt . Errorf ( "should have no content type and %s is present" , ct )
}
return nil
} )
c . Assert ( err , checker . IsNil )
2022-11-29 10:48:05 +00:00
err = try . GetRequest ( "http://127.0.0.1:8000/autodetect/css/ct" , time . Second , try . HasHeaderValue ( "Content-Type" , "text/css" , false ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/autodetect/pdf/ct" , time . Second , try . HasHeaderValue ( "Content-Type" , "application/pdf" , false ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/autodetect/css/noct" , time . Second , try . HasHeaderValue ( "Content-Type" , "text/plain; charset=utf-8" , false ) )
c . Assert ( err , checker . IsNil )
err = try . GetRequest ( "http://127.0.0.1:8000/autodetect/pdf/noct" , time . Second , try . HasHeaderValue ( "Content-Type" , "application/pdf" , false ) )
c . Assert ( err , checker . IsNil )
2020-01-21 17:06:03 +00:00
}
2022-06-27 13:16:08 +00:00
func ( s * SimpleSuite ) TestMuxer ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeUp ( c )
defer s . composeDown ( c )
whoami1URL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami1" ) , "80" )
file := s . adaptFile ( c , "fixtures/simple_muxer.toml" , struct {
Server1 string
} { whoami1URL } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "!Host" ) )
c . Assert ( err , checker . IsNil )
testCases := [ ] struct {
desc string
request string
target string
body string
expected int
} {
{
desc : "!Host with absolute-form URL with empty host and host header, no match" ,
request : "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n" ,
target : "127.0.0.1:8000" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!Host with absolute-form URL with empty host and host header, match" ,
request : "GET http://@/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n" ,
target : "127.0.0.1:8000" ,
expected : http . StatusOK ,
} ,
{
desc : "!Host with absolute-form URL and host header, no match" ,
request : "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n" ,
target : "127.0.0.1:8000" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!Host with absolute-form URL and host header, match" ,
request : "GET http://toto.localhost/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n" ,
target : "127.0.0.1:8000" ,
expected : http . StatusOK ,
} ,
{
desc : "!HostRegexp with absolute-form URL with empty host and host header, no match" ,
request : "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n" ,
target : "127.0.0.1:8001" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!HostRegexp with absolute-form URL with empty host and host header, match" ,
request : "GET http://@/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n" ,
target : "127.0.0.1:8001" ,
expected : http . StatusOK ,
} ,
{
desc : "!HostRegexp with absolute-form URL and host header, no match" ,
request : "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n" ,
target : "127.0.0.1:8001" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!HostRegexp with absolute-form URL and host header, match" ,
request : "GET http://toto.localhost/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n" ,
target : "127.0.0.1:8001" ,
expected : http . StatusOK ,
} ,
{
2022-11-28 14:48:05 +00:00
desc : "!Query with semicolon and empty query param value, no match" ,
2022-06-27 13:16:08 +00:00
request : "GET /?foo=; HTTP/1.1\r\nHost: other.localhost\r\n\r\n" ,
target : "127.0.0.1:8002" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!Query with semicolon, no match" ,
request : "GET /?foo=titi;bar=toto HTTP/1.1\r\nHost: other.localhost\r\n\r\n" ,
target : "127.0.0.1:8002" ,
expected : http . StatusNotFound ,
} ,
{
desc : "!Query with semicolon, match" ,
request : "GET /?bar=toto;boo=titi HTTP/1.1\r\nHost: other.localhost\r\n\r\n" ,
target : "127.0.0.1:8002" ,
expected : http . StatusOK ,
body : "bar=toto&boo=titi" ,
} ,
}
for _ , test := range testCases {
conn , err := net . Dial ( "tcp" , test . target )
c . Assert ( err , checker . IsNil )
_ , err = conn . Write ( [ ] byte ( test . request ) )
c . Assert ( err , checker . IsNil )
resp , err := http . ReadResponse ( bufio . NewReader ( conn ) , nil )
c . Assert ( err , checker . IsNil )
2022-11-28 14:48:05 +00:00
c . Assert ( resp . StatusCode , checker . Equals , test . expected , check . Commentf ( test . desc ) )
2022-06-27 13:16:08 +00:00
if test . body != "" {
body , err := io . ReadAll ( resp . Body )
c . Assert ( err , checker . IsNil )
c . Assert ( string ( body ) , checker . Contains , test . body )
}
}
}
2022-12-05 10:30:05 +00:00
func ( s * SimpleSuite ) TestDebugLog ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeUp ( c )
defer s . composeDown ( c )
file := s . adaptFile ( c , "fixtures/simple_debug_log.toml" , struct { } { } )
defer os . Remove ( file )
cmd , output := s . cmdTraefik ( withConfigFile ( file ) )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "PathPrefix(`/whoami`)" ) )
c . Assert ( err , checker . IsNil )
req , err := http . NewRequest ( http . MethodGet , "http://localhost:8000/whoami" , http . NoBody )
c . Assert ( err , checker . IsNil )
req . Header . Set ( "Autorization" , "Bearer ThisIsABearerToken" )
response , err := http . DefaultClient . Do ( req )
c . Assert ( err , checker . IsNil )
c . Assert ( response . StatusCode , checker . Equals , http . StatusOK )
if regexp . MustCompile ( "ThisIsABearerToken" ) . MatchReader ( output ) {
c . Logf ( "Traefik Logs: %s" , output . String ( ) )
c . Log ( "Found Authorization Header in Traefik DEBUG logs" )
c . Fail ( )
}
}
2023-06-15 16:20:06 +00:00
func ( s * SimpleSuite ) TestEncodeSemicolons ( c * check . C ) {
s . createComposeProject ( c , "base" )
s . composeUp ( c )
defer s . composeDown ( c )
whoami1URL := "http://" + net . JoinHostPort ( s . getComposeServiceIP ( c , "whoami1" ) , "80" )
file := s . adaptFile ( c , "fixtures/simple_encode_semicolons.toml" , struct {
Server1 string
} { whoami1URL } )
defer os . Remove ( file )
cmd , output := s . traefikCmd ( withConfigFile ( file ) )
defer output ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
defer s . killCmd ( cmd )
err = try . GetRequest ( "http://127.0.0.1:8080/api/rawdata" , 1 * time . Second , try . BodyContains ( "Host(`other.localhost`)" ) )
c . Assert ( err , checker . IsNil )
testCases := [ ] struct {
desc string
request string
target string
body string
expected int
} {
{
desc : "Transforming semicolons" ,
request : "GET /?bar=toto;boo=titi HTTP/1.1\r\nHost: other.localhost\r\n\r\n" ,
target : "127.0.0.1:8000" ,
expected : http . StatusOK ,
body : "bar=toto&boo=titi" ,
} ,
{
desc : "Encoding semicolons" ,
request : "GET /?bar=toto&boo=titi;aaaa HTTP/1.1\r\nHost: other.localhost\r\n\r\n" ,
target : "127.0.0.1:8001" ,
expected : http . StatusOK ,
body : "bar=toto&boo=titi%3Baaaa" ,
} ,
}
for _ , test := range testCases {
conn , err := net . Dial ( "tcp" , test . target )
c . Assert ( err , checker . IsNil )
_ , err = conn . Write ( [ ] byte ( test . request ) )
c . Assert ( err , checker . IsNil )
resp , err := http . ReadResponse ( bufio . NewReader ( conn ) , nil )
c . Assert ( err , checker . IsNil )
if resp . StatusCode != test . expected {
c . Errorf ( "%s failed with %d instead of %d" , test . desc , resp . StatusCode , test . expected )
}
if test . body != "" {
body , err := io . ReadAll ( resp . Body )
c . Assert ( err , checker . IsNil )
c . Assert ( string ( body ) , checker . Contains , test . body )
}
}
}