diff options
Diffstat (limited to 'internal/redirects/validations_test.go')
-rw-r--r-- | internal/redirects/validations_test.go | 325 |
1 files changed, 321 insertions, 4 deletions
diff --git a/internal/redirects/validations_test.go b/internal/redirects/validations_test.go index 2b8ac1b1..13f115cd 100644 --- a/internal/redirects/validations_test.go +++ b/internal/redirects/validations_test.go @@ -2,6 +2,7 @@ package redirects import ( "fmt" + "net/http" "strings" "testing" @@ -11,7 +12,68 @@ import ( "gitlab.com/gitlab-org/gitlab-pages/internal/feature" ) -func TestRedirectsValidateUrl(t *testing.T) { +func TestRedirectsValidateFromUrl(t *testing.T) { + t.Setenv(feature.RedirectsPlaceholders.EnvVariable, "true") + + tests := map[string]struct { + url string + expectedErr error + }{ + "valid_url": { + url: "/goto.html", + }, + "no_domain_level_redirects": { + url: "https://GitLab.com", + }, + "no_special_characters_escape_domain_level_redirects": { + url: "/\\GitLab.com", + expectedErr: errNoValidStartingInURLPath, + }, + "no_schemaless_url_domain_level_redirects": { + url: "//GitLab.com/pages.html", + expectedErr: errNoValidStartingInURLPath, + }, + "no_bare_domain_level_redirects": { + url: "GitLab.com", + expectedErr: errNoValidStartingInURLPath, + }, + "no_parent_traversing_relative_url": { + url: "../target.html", + expectedErr: errNoValidStartingInURLPath, + }, + "too_many_slashes": { + url: strings.Repeat("/a", 26), + expectedErr: fmt.Errorf("url path cannot contain more than %d forward slashes", defaultMaxPathSegments), + }, + "placeholders": { + url: "/news/:year/:month/:date/:slug", + }, + "splats": { + url: "/blog/*", + }, + "no_multiple_splats_redirects": { + url: "/foo/*/bar/*/baz", + expectedErr: errMoreThanOneSplats, + }, + "splat_placeholders": { + url: "/new/path/:splat", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + err := validateFromURL(tt.url) + if tt.expectedErr != nil { + require.EqualError(t, err, tt.expectedErr.Error()) + return + } + + require.NoError(t, err) + }) + } +} + +func TestRedirectsValidateToUrl(t *testing.T) { t.Setenv(feature.RedirectsPlaceholders.EnvVariable, "true") tests := map[string]struct { @@ -58,7 +120,7 @@ func TestRedirectsValidateUrl(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { - err := validateURL(tt.url) + err := validateToURL(tt.url, http.StatusMovedPermanently) if tt.expectedErr != nil { require.EqualError(t, err, tt.expectedErr.Error()) return @@ -92,7 +154,7 @@ func TestRedirectsValidateUrlNoPlaceholders(t *testing.T) { for name, tt := range tests { t.Run(name, func(t *testing.T) { - err := validateURL(tt.url) + err := validateToURL(tt.url, http.StatusMovedPermanently) require.ErrorIs(t, err, tt.expectedErr) }) } @@ -108,9 +170,12 @@ func TestRedirectsValidateRule(t *testing.T) { "valid_rule": { rule: "/goto.html /target.html 301", }, + "valid_from_host_url": { + rule: "http://valid.com/ /teapot.html 302", + }, "invalid_from_url": { rule: "invalid.com /teapot.html 302", - expectedErr: errNoStartingForwardSlashInURLPath, + expectedErr: errNoValidStartingInURLPath, }, "invalid_to_url": { rule: "/goto.html invalid.com", @@ -140,3 +205,255 @@ func TestRedirectsValidateRule(t *testing.T) { }) } } + +func TestRedirectsValidateFromUrl_DomainRedirect_Enabled(t *testing.T) { + t.Setenv(feature.RedirectsPlaceholders.EnvVariable, "true") + + tests := map[string]struct { + url string + expectedErr error + }{ + "valid_url": { + url: "/goto.html", + }, + "domain_level": { + url: "https://GitLab.com", + }, + "no_special_characters_escape_domain_level": { + url: "/\\GitLab.com", + expectedErr: errNoValidStartingInURLPath, + }, + "no_schemaless_url_domain_level": { + url: "//GitLab.com/pages.html", + expectedErr: errNoValidStartingInURLPath, + }, + "no_bare_domain_level": { + url: "GitLab.com", + expectedErr: errNoValidStartingInURLPath, + }, + "no_parent_traversing_relative_url": { + url: "../target.html", + expectedErr: errNoValidStartingInURLPath, + }, + "too_many_slashes": { + url: strings.Repeat("/a", 26), + expectedErr: fmt.Errorf("url path cannot contain more than %d forward slashes", defaultMaxPathSegments), + }, + "placeholders": { + url: "/news/:year/:month/:date/:slug", + }, + "domain_redirect_placeholders": { + url: "https://GitLab.com/news/:year/:month/:date/:slug", + }, + "splats": { + url: "/blog/*", + }, + "lone_splats": { + url: "https://GitLab.com/*", + }, + "domain_redirect_splats": { + url: "https://GitLab.com/blog/*", + }, + "splat_placeholders": { + url: "/new/path/:splat", + }, + "domain_redirect_splat_placeholders": { + url: "https://GitLab.com/new/path/:splat", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + err := validateFromURL(tt.url) + if tt.expectedErr != nil { + require.EqualError(t, err, tt.expectedErr.Error()) + return + } + + require.NoError(t, err) + }) + } +} + +func TestRedirectsValidateToUrl_DomainRedirect_Enabled(t *testing.T) { + t.Setenv(feature.RedirectsPlaceholders.EnvVariable, "true") + t.Setenv(feature.DomainRedirects.EnvVariable, "true") + + tests := map[string]struct { + url string + status int + expectedErr error + }{ + "valid_url": { + url: "/goto.html", + status: http.StatusOK, + }, + "domain_level_redirects": { + url: "https://GitLab.com", + status: http.StatusMovedPermanently, + }, + "domain_level_rewrite": { + url: "https://GitLab.com", + status: http.StatusOK, + expectedErr: errNoDomainLevelRewrite, + }, + "no_special_characters_escape_domain_level_redirects": { + url: "/\\GitLab.com", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_schemaless_url_domain_level_redirects": { + url: "//GitLab.com/pages.html", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_bare_domain_level_redirects": { + url: "GitLab.com", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_parent_traversing_relative_url": { + url: "../target.html", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "too_many_slashes": { + url: strings.Repeat("/a", 26), + status: http.StatusMovedPermanently, + expectedErr: fmt.Errorf("url path cannot contain more than %d forward slashes", defaultMaxPathSegments), + }, + "placeholders": { + url: "/news/:year/:month/:date/:slug", + status: http.StatusMovedPermanently, + }, + "domain_redirect_placeholders": { + url: "https://GitLab.com/news/:year/:month/:date/:slug", + status: http.StatusMovedPermanently, + }, + "splats": { + url: "/blog/*", + status: http.StatusMovedPermanently, + }, + "lone_splats": { + url: "https://GitLab.com/*", + status: http.StatusMovedPermanently, + }, + "domain_redirect_splats": { + url: "https://GitLab.com/blog/*", + status: http.StatusMovedPermanently, + }, + "splat_placeholders": { + url: "/new/path/:splat", + status: http.StatusMovedPermanently, + }, + "domain_redirect_splat_placeholders": { + url: "https://GitLab.com/new/path/:splat", + status: http.StatusMovedPermanently, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + err := validateToURL(tt.url, tt.status) + if tt.expectedErr != nil { + require.EqualError(t, err, tt.expectedErr.Error()) + return + } + + require.NoError(t, err) + }) + } +} + +// Tests validation rules that only apply when the `FF_ENABLE_DOMAIN_REDIRECT` +// feature flag is not enabled. These tests can be removed when the +// `FF_ENABLE_DOMAIN_REDIRECT` flag is removed. +func TestRedirectsValidateToUrl_DomainRedirect_Disabled(t *testing.T) { + t.Setenv(feature.RedirectsPlaceholders.EnvVariable, "true") + t.Setenv(feature.DomainRedirects.EnvVariable, "true") + + tests := map[string]struct { + url string + status int + expectedErr error + }{ + "valid_url": { + url: "/goto.html", + status: http.StatusOK, + }, + "domain_level_redirects": { + url: "https://GitLab.com", + status: http.StatusMovedPermanently, + }, + "domain_level_rewrite": { + url: "https://GitLab.com", + status: http.StatusOK, + expectedErr: errNoDomainLevelRewrite, + }, + "no_special_characters_escape_domain_level_redirects": { + url: "/\\GitLab.com", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_schemaless_url_domain_level_redirects": { + url: "//GitLab.com/pages.html", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_bare_domain_level_redirects": { + url: "GitLab.com", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "no_parent_traversing_relative_url": { + url: "../target.html", + status: http.StatusMovedPermanently, + expectedErr: errNoValidStartingInURLPath, + }, + "too_many_slashes": { + url: strings.Repeat("/a", 26), + status: http.StatusMovedPermanently, + expectedErr: fmt.Errorf("url path cannot contain more than %d forward slashes", defaultMaxPathSegments), + }, + "placeholders": { + url: "/news/:year/:month/:date/:slug", + status: http.StatusMovedPermanently, + }, + "domain_redirect_placeholders": { + url: "https://GitLab.com/news/:year/:month/:date/:slug", + status: http.StatusMovedPermanently, + }, + "splats": { + url: "/blog/*", + status: http.StatusMovedPermanently, + }, + "lone_splats": { + url: "https://GitLab.com/*", + status: http.StatusMovedPermanently, + }, + "domain_redirect_splats": { + url: "https://GitLab.com/blog/*", + status: http.StatusMovedPermanently, + }, + "splat_placeholders": { + url: "/new/path/:splat", + status: http.StatusMovedPermanently, + }, + "domain_redirect_splat_placeholders": { + url: "https://GitLab.com/new/path/:splat", + status: http.StatusMovedPermanently, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + err := validateToURL(tt.url, tt.status) + if tt.expectedErr != nil { + require.EqualError(t, err, tt.expectedErr.Error()) + return + } + + require.NoError(t, err) + }) + } +} |