2019-04-02 03:40:04 -05:00
package integration
import (
2023-09-22 11:00:07 +02:00
"net"
2019-04-02 03:40:04 -05:00
"net/http"
2023-09-22 11:00:07 +02:00
"net/http/httptest"
2019-07-15 10:22:03 +02:00
"os"
2019-04-02 03:40:04 -05:00
"time"
"github.com/go-check/check"
2020-09-16 15:46:04 +02:00
"github.com/traefik/traefik/v2/integration/try"
2019-04-02 03:40:04 -05:00
checker "github.com/vdemeester/shakers"
)
2020-05-11 12:06:07 +02:00
// Headers tests suite.
2019-04-02 03:40:04 -05:00
type HeadersSuite struct { BaseSuite }
func ( s * HeadersSuite ) TestSimpleConfiguration ( c * check . C ) {
cmd , display := s . traefikCmd ( withConfigFile ( "fixtures/headers/basic.toml" ) )
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 09:32:03 +02:00
defer s . killCmd ( cmd )
2019-04-02 03:40:04 -05:00
// Expected a 404 as we did not configure anything
err = try . GetRequest ( "http://127.0.0.1:8000/" , 1000 * time . Millisecond , try . StatusCodeIs ( http . StatusNotFound ) )
c . Assert ( err , checker . IsNil )
}
2023-09-22 11:00:07 +02:00
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 )
}
2019-04-02 03:40:04 -05:00
func ( s * HeadersSuite ) TestCorsResponses ( c * check . C ) {
2019-07-15 10:22:03 +02:00
file := s . adaptFile ( c , "fixtures/headers/cors.toml" , struct { } { } )
defer os . Remove ( file )
cmd , display := s . traefikCmd ( withConfigFile ( file ) )
2019-04-02 03:40:04 -05:00
defer display ( c )
err := cmd . Start ( )
c . Assert ( err , checker . IsNil )
2020-10-09 09:32:03 +02:00
defer s . killCmd ( cmd )
2019-04-02 03:40:04 -05:00
2020-07-17 15:38:04 +02:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2019-07-12 03:46:04 -06:00
defer backend . Close ( )
err = try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
2019-04-02 03:40:04 -05:00
testCase := [ ] struct {
desc string
requestHeaders http . Header
expected http . Header
2019-07-12 03:46:04 -06:00
reqHost string
method string
2019-04-02 03:40:04 -05: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 03:46:04 -06:00
reqHost : "test.localhost" ,
method : http . MethodGet ,
2019-04-02 03:40:04 -05: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 03:46:04 -06: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 03:40:04 -05:00
} ,
}
for _ , test := range testCase {
2019-07-12 03:46:04 -06:00
req , err := http . NewRequest ( test . method , "http://127.0.0.1:8000/" , nil )
2019-04-02 03:40:04 -05:00
c . Assert ( err , checker . IsNil )
2019-07-12 03:46:04 -06:00
req . Host = test . reqHost
2019-04-02 03:40:04 -05:00
req . Header = test . requestHeaders
2019-07-12 03:46:04 -06:00
err = try . Request ( req , 500 * time . Millisecond , try . HasHeaderStruct ( test . expected ) )
2019-04-02 03:40:04 -05:00
c . Assert ( err , checker . IsNil )
}
}
2019-07-29 08:12:05 -06:00
func ( s * HeadersSuite ) TestSecureHeadersResponses ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/headers/secure.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 09:32:03 +02:00
defer s . killCmd ( cmd )
2019-07-29 08:12:05 -06:00
2020-07-17 15:38:04 +02:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2019-07-29 08:12:05 -06:00
defer backend . Close ( )
err = try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
testCase := [ ] struct {
2020-06-15 12:20:05 +02:00
desc string
expected http . Header
reqHost string
internalReqHost string
2019-07-29 08:12:05 -06:00
} {
{
2021-06-21 21:16:13 +08:00
desc : "Permissions-Policy Set" ,
2019-07-29 08:12:05 -06:00
expected : http . Header {
2021-06-21 21:16:13 +08:00
"Permissions-Policy" : { "microphone=()," } ,
2019-07-29 08:12:05 -06:00
} ,
2020-06-15 12:20:05 +02:00
reqHost : "test.localhost" ,
internalReqHost : "internal.localhost" ,
2019-07-29 08:12:05 -06:00
} ,
}
for _ , test := range testCase {
req , err := http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/" , nil )
c . Assert ( err , checker . IsNil )
req . Host = test . reqHost
2020-06-15 12:20:05 +02:00
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasHeaderStruct ( test . expected ) )
c . Assert ( err , checker . IsNil )
req , err = http . NewRequest ( http . MethodGet , "http://127.0.0.1:8000/api/rawdata" , nil )
c . Assert ( err , checker . IsNil )
req . Host = test . internalReqHost
err = try . Request ( req , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) , try . HasHeaderStruct ( test . expected ) )
2019-07-29 08:12:05 -06:00
c . Assert ( err , checker . IsNil )
}
}
2020-07-01 01:42:04 -07:00
func ( s * HeadersSuite ) TestMultipleSecureHeadersResponses ( c * check . C ) {
file := s . adaptFile ( c , "fixtures/headers/secure_multiple.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 09:32:03 +02:00
defer s . killCmd ( cmd )
2020-07-01 01:42:04 -07:00
2020-07-22 14:39:45 +02:00
backend := startTestServer ( "9000" , http . StatusOK , "" )
2020-07-01 01:42:04 -07:00
defer backend . Close ( )
err = try . GetRequest ( backend . URL , 500 * time . Millisecond , try . StatusCodeIs ( http . StatusOK ) )
c . Assert ( err , checker . IsNil )
testCase := [ ] struct {
desc string
expected http . Header
reqHost string
} {
{
2021-06-21 21:16:13 +08:00
desc : "Multiple Secure Headers Set" ,
2020-07-01 01:42:04 -07: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 )
c . Assert ( err , checker . IsNil )
req . Host = test . reqHost
err = try . Request ( req , 500 * time . Millisecond , try . HasHeaderStruct ( test . expected ) )
c . Assert ( err , checker . IsNil )
}
}