package redirect import ( "net/http" "net/http/httptest" "testing" "github.com/containous/traefik/configuration" "github.com/containous/traefik/testhelpers" "github.com/containous/traefik/tls" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestNewEntryPointHandler(t *testing.T) { testCases := []struct { desc string entryPoint *configuration.EntryPoint permanent bool url string expectedURL string expectedStatus int errorExpected bool }{ { desc: "HTTP to HTTPS", entryPoint: &configuration.EntryPoint{Address: ":443", TLS: &tls.TLS{}}, url: "http://foo:80", expectedURL: "https://foo:443", expectedStatus: http.StatusFound, }, { desc: "HTTPS to HTTP", entryPoint: &configuration.EntryPoint{Address: ":80"}, url: "https://foo:443", expectedURL: "http://foo:80", expectedStatus: http.StatusFound, }, { desc: "HTTP to HTTP", entryPoint: &configuration.EntryPoint{Address: ":88"}, url: "http://foo:80", expectedURL: "http://foo:88", expectedStatus: http.StatusFound, }, { desc: "HTTP to HTTPS permanent", entryPoint: &configuration.EntryPoint{Address: ":443", TLS: &tls.TLS{}}, permanent: true, url: "http://foo:80", expectedURL: "https://foo:443", expectedStatus: http.StatusMovedPermanently, }, { desc: "HTTPS to HTTP permanent", entryPoint: &configuration.EntryPoint{Address: ":80"}, permanent: true, url: "https://foo:443", expectedURL: "http://foo:80", expectedStatus: http.StatusMovedPermanently, }, { desc: "invalid address", entryPoint: &configuration.EntryPoint{Address: ":foo", TLS: &tls.TLS{}}, url: "http://foo:80", errorExpected: true, }, } for _, test := range testCases { test := test t.Run(test.desc, func(t *testing.T) { t.Parallel() handler, err := NewEntryPointHandler(test.entryPoint, test.permanent) if test.errorExpected { require.Error(t, err) } else { require.NoError(t, err) recorder := httptest.NewRecorder() r := testhelpers.MustNewRequest(http.MethodGet, test.url, nil) handler.ServeHTTP(recorder, r, nil) location, err := recorder.Result().Location() require.NoError(t, err) assert.Equal(t, test.expectedURL, location.String()) assert.Equal(t, test.expectedStatus, recorder.Code) } }) } } func TestNewRegexHandler(t *testing.T) { testCases := []struct { desc string regex string replacement string permanent bool url string expectedURL string expectedStatus int errorExpected bool }{ { desc: "simple redirection", regex: `^(?:http?:\/\/)(foo)(\.com)(:\d+)(.*)$`, replacement: "https://${1}bar$2:443$4", url: "http://foo.com:80", expectedURL: "https://foobar.com:443", expectedStatus: http.StatusFound, }, { desc: "use request header", regex: `^(?:http?:\/\/)(foo)(\.com)(:\d+)(.*)$`, replacement: `https://${1}{{ .Request.Header.Get "X-Foo" }}$2:443$4`, url: "http://foo.com:80", expectedURL: "https://foobar.com:443", expectedStatus: http.StatusFound, }, { desc: "URL doesn't match regex", regex: `^(?:http?:\/\/)(foo)(\.com)(:\d+)(.*)$`, replacement: "https://${1}bar$2:443$4", url: "http://bar.com:80", expectedStatus: http.StatusOK, }, { desc: "invalid rewritten URL", regex: `^(.*)$`, replacement: "http://192.168.0.%31/", url: "http://foo.com:80", expectedStatus: http.StatusBadGateway, }, { desc: "invalid regex", regex: `^(.*`, replacement: "$1", url: "http://foo.com:80", errorExpected: true, }, } for _, test := range testCases { test := test t.Run(test.desc, func(t *testing.T) { t.Parallel() handler, err := NewRegexHandler(test.regex, test.replacement, test.permanent) if test.errorExpected { require.Nil(t, handler) require.Error(t, err) } else { require.NotNil(t, handler) require.NoError(t, err) recorder := httptest.NewRecorder() r := testhelpers.MustNewRequest(http.MethodGet, test.url, nil) r.Header.Set("X-Foo", "bar") next := func(rw http.ResponseWriter, req *http.Request) {} handler.ServeHTTP(recorder, r, next) if test.expectedStatus == http.StatusMovedPermanently || test.expectedStatus == http.StatusFound { assert.Equal(t, test.expectedStatus, recorder.Code) location, err := recorder.Result().Location() require.NoError(t, err) assert.Equal(t, test.expectedURL, location.String()) } else { assert.Equal(t, test.expectedStatus, recorder.Code) location, err := recorder.Result().Location() require.Errorf(t, err, "Location %v", location) } } }) } }