2019-04-02 11:40:04 +03:00
package integration
import (
2023-09-22 12:00:07 +03:00
"net"
2019-04-02 11:40:04 +03:00
"net/http"
2023-09-22 12:00:07 +03:00
"net/http/httptest"
2024-01-09 19:00:07 +03:00
"testing"
2019-04-02 11:40:04 +03:00
"time"
2024-01-09 19:00:07 +03:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
2023-02-03 17:24:05 +03:00
"github.com/traefik/traefik/v3/integration/try"
2019-04-02 11:40:04 +03:00
)
2020-05-11 13:06:07 +03:00
// Headers tests suite.
2019-04-02 11:40:04 +03:00
type HeadersSuite struct { BaseSuite }
2024-01-09 19:00:07 +03:00
func TestHeadersSuite ( t * testing . T ) {
suite . Run ( t , new ( HeadersSuite ) )
}
func ( s * HeadersSuite ) TestSimpleConfiguration ( ) {
s . traefikCmd ( withConfigFile ( "fixtures/headers/basic.toml" ) )
2019-04-02 11:40:04 +03:00
// Expected a 404 as we did not configure anything
2024-01-09 19:00:07 +03:00
err := try . GetRequest ( "http://127.0.0.1:8000/" , 1000 * time . Millisecond , try . StatusCodeIs ( http . StatusNotFound ) )
require . NoError ( s . T ( ) , err )
2019-04-02 11:40:04 +03:00
}
2024-01-09 19:00:07 +03:00
func ( s * HeadersSuite ) TestReverseProxyHeaderRemoved ( ) {
file := s . adaptFile ( "fixtures/headers/remove_reverseproxy_headers.toml" , struct { } { } )
s . traefikCmd ( withConfigFile ( file ) )
2023-09-22 12:00:07 +03:00
handler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
_ , found := r . Header [ "X-Forwarded-Host" ]
2024-01-09 19:00:07 +03:00
assert . True ( s . T ( ) , found )
2023-09-22 12:00:07 +03:00
_ , found = r . Header [ "Foo" ]
2024-01-09 19:00:07 +03:00
assert . False ( s . T ( ) , found )
2023-09-22 12:00:07 +03:00
_ , found = r . Header [ "X-Forwarded-For" ]
2024-01-09 19:00:07 +03:00
assert . False ( s . T ( ) , found )
2023-09-22 12:00:07 +03:00
} )
listener , err := net . Listen ( "tcp" , "127.0.0.1:9000" )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2023-09-22 12:00:07 +03:00
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 )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2023-09-22 12:00:07 +03:00
req . Host = "test.localhost"
req . Header = http . Header {
"Foo" : { "bar" } ,
}
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2023-09-22 12:00:07 +03:00
}
2024-01-09 19:00:07 +03:00
func ( s * HeadersSuite ) TestCorsResponses ( ) {
file := s . adaptFile ( "fixtures/headers/cors.toml" , struct { } { } )
s . traefikCmd ( withConfigFile ( file ) )
2019-04-02 11:40:04 +03:00
2020-07-17 16:38:04 +03:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2019-07-12 12:46:04 +03:00
defer backend . Close ( )
2024-01-09 19:00:07 +03:00
err := try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
require . NoError ( s . T ( ) , err )
2019-07-12 12:46:04 +03:00
2019-04-02 11:40:04 +03:00
testCase := [ ] struct {
desc string
requestHeaders http . Header
expected http . Header
2019-07-12 12:46:04 +03:00
reqHost string
method string
2019-04-02 11:40:04 +03:00
} {
{
desc : "simple access control allow origin" ,
requestHeaders : http . Header {
"Origin" : { "https://foo.bar.org" } ,
} ,
expected : http . Header {
"Access-Control-Allow-Origin" : { "https://foo.bar.org" } ,
"Vary" : { "Origin" } ,
} ,
2019-07-12 12:46:04 +03:00
reqHost : "test.localhost" ,
method : http . MethodGet ,
2019-04-02 11:40:04 +03:00
} ,
{
desc : "simple preflight request" ,
requestHeaders : http . Header {
"Access-Control-Request-Headers" : { "origin" } ,
"Access-Control-Request-Method" : { "GET" , "OPTIONS" } ,
"Origin" : { "https://foo.bar.org" } ,
} ,
expected : http . Header {
"Access-Control-Allow-Origin" : { "https://foo.bar.org" } ,
"Access-Control-Max-Age" : { "100" } ,
"Access-Control-Allow-Methods" : { "GET,OPTIONS,PUT" } ,
} ,
2019-07-12 12:46:04 +03:00
reqHost : "test.localhost" ,
method : http . MethodOptions ,
} ,
{
desc : "preflight Options request with no cors configured" ,
requestHeaders : http . Header {
"Access-Control-Request-Headers" : { "origin" } ,
"Access-Control-Request-Method" : { "GET" , "OPTIONS" } ,
"Origin" : { "https://foo.bar.org" } ,
} ,
expected : http . Header {
"X-Custom-Response-Header" : { "True" } ,
} ,
reqHost : "test2.localhost" ,
method : http . MethodOptions ,
} ,
{
desc : "preflight Get request with no cors configured" ,
requestHeaders : http . Header {
"Access-Control-Request-Headers" : { "origin" } ,
"Access-Control-Request-Method" : { "GET" , "OPTIONS" } ,
"Origin" : { "https://foo.bar.org" } ,
} ,
expected : http . Header {
"X-Custom-Response-Header" : { "True" } ,
} ,
reqHost : "test2.localhost" ,
method : http . MethodGet ,
2019-04-02 11:40:04 +03:00
} ,
}
for _ , test := range testCase {
2019-07-12 12:46:04 +03:00
req , err := http . NewRequest ( test . method , "http://127.0.0.1:8000/" , nil )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2019-07-12 12:46:04 +03:00
req . Host = test . reqHost
2019-04-02 11:40:04 +03:00
req . Header = test . requestHeaders
2019-07-12 12:46:04 +03:00
err = try . Request ( req , 500 * time . Millisecond , try . HasHeaderStruct ( test . expected ) )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2019-04-02 11:40:04 +03:00
}
}
2019-07-29 17:12:05 +03:00
2024-01-09 19:00:07 +03:00
func ( s * HeadersSuite ) TestSecureHeadersResponses ( ) {
file := s . adaptFile ( "fixtures/headers/secure.toml" , struct { } { } )
s . traefikCmd ( withConfigFile ( file ) )
2019-07-29 17:12:05 +03:00
2020-07-17 16:38:04 +03:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2019-07-29 17:12:05 +03:00
defer backend . Close ( )
2024-01-09 19:00:07 +03:00
err := try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
require . NoError ( s . T ( ) , err )
2019-07-29 17:12:05 +03:00
testCase := [ ] struct {
2020-06-15 13:20:05 +03:00
desc string
expected http . Header
reqHost string
internalReqHost string
2019-07-29 17:12:05 +03:00
} {
{
2021-06-21 16:16:13 +03:00
desc : "Permissions-Policy Set" ,
2019-07-29 17:12:05 +03:00
expected : http . Header {
2021-06-21 16:16:13 +03:00
"Permissions-Policy" : { "microphone=()," } ,
2019-07-29 17:12:05 +03:00
} ,
2020-06-15 13:20:05 +03:00
reqHost : "test.localhost" ,
internalReqHost : "internal.localhost" ,
2019-07-29 17:12:05 +03:00
} ,
}
for _ , test := range testCase {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2019-07-29 17:12:05 +03:00
req . Host = test . reqHost
2020-06-15 13:20:05 +03:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasHeaderStruct ( test . expected ) )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2020-06-15 13:20:05 +03:00
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/api/rawdata" , nil )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2020-06-15 13:20:05 +03:00
req . Host = test . internalReqHost
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasHeaderStruct ( test . expected ) )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2019-07-29 17:12:05 +03:00
}
}
2020-07-01 11:42:04 +03:00
2024-01-09 19:00:07 +03:00
func ( s * HeadersSuite ) TestMultipleSecureHeadersResponses ( ) {
file := s . adaptFile ( "fixtures/headers/secure_multiple.toml" , struct { } { } )
s . traefikCmd ( withConfigFile ( file ) )
2020-07-01 11:42:04 +03:00
2020-07-22 15:39:45 +03:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2020-07-01 11:42:04 +03:00
defer backend . Close ( )
2024-01-09 19:00:07 +03:00
err := try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
require . NoError ( s . T ( ) , err )
2020-07-01 11:42:04 +03:00
testCase := [ ] struct {
desc string
expected http . Header
reqHost string
} {
{
2021-06-21 16:16:13 +03:00
desc : "Multiple Secure Headers Set" ,
2020-07-01 11:42:04 +03:00
expected : http . Header {
"X-Frame-Options" : { "DENY" } ,
"X-Content-Type-Options" : { "nosniff" } ,
} ,
reqHost : "test.localhost" ,
} ,
}
for _ , test := range testCase {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2020-07-01 11:42:04 +03:00
req . Host = test . reqHost
err = try . Request ( req , 500 * time . Millisecond , try . HasHeaderStruct ( test . expected ) )
2024-01-09 19:00:07 +03:00
require . NoError ( s . T ( ) , err )
2020-07-01 11:42:04 +03:00
}
}