diff options
author | Eric Eastwood <contact@ericeastwood.com> | 2020-08-28 00:26:23 +0300 |
---|---|---|
committer | Vladimir Shushlin <v.shushlin@gmail.com> | 2020-09-15 11:35:23 +0300 |
commit | 7914c901b00cd3568ef4435ff79aa1bbea8aa4b6 (patch) | |
tree | 995d157f186878c2ed804e40269b78f149e81b93 /internal/serving | |
parent | 0abe5dd1422e2fb86cda77ca9151df157cbcfd8b (diff) |
Add support for redirects24-add-redirects
Fix https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24
Diffstat (limited to 'internal/serving')
-rw-r--r-- | internal/serving/disk/reader.go | 42 | ||||
-rw-r--r-- | internal/serving/disk/serving.go | 14 | ||||
-rw-r--r-- | internal/serving/disk/symlink/path_test.go | 23 |
3 files changed, 59 insertions, 20 deletions
diff --git a/internal/serving/disk/reader.go b/internal/serving/disk/reader.go index 0d11a184..350d036b 100644 --- a/internal/serving/disk/reader.go +++ b/internal/serving/disk/reader.go @@ -5,12 +5,14 @@ import ( "fmt" "io" "net/http" + "os" "strconv" "strings" "time" "github.com/prometheus/client_golang/prometheus" + "gitlab.com/gitlab-org/gitlab-pages/internal/redirects" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk/symlink" "gitlab.com/gitlab-org/gitlab-pages/internal/vfs" @@ -22,6 +24,34 @@ type Reader struct { vfs vfs.VFS } +// Show the user some validation messages for their _redirects file +func (reader *Reader) serveRedirectsStatus(h serving.Handler, redirects *redirects.Redirects) error { + h.Writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + h.Writer.Header().Set("X-Content-Type-Options", "nosniff") + h.Writer.WriteHeader(http.StatusOK) + _, err := fmt.Fprintln(h.Writer, redirects.Status()) + return err +} + +func (reader *Reader) tryRedirects(h serving.Handler) error { + ctx := h.Request.Context() + root, err := reader.vfs.Root(ctx, h.LookupPath.Path) + if err != nil { + return err + } + + r := redirects.ParseRedirects(ctx, root) + + rewrittenURL, status, err := r.Rewrite(h.Request.URL) + if err != nil { + return err + } + + http.Redirect(h.Writer, h.Request, rewrittenURL.Path, status) + + return nil +} + func (reader *Reader) tryFile(h serving.Handler) error { ctx := h.Request.Context() @@ -62,6 +92,18 @@ func (reader *Reader) tryFile(h serving.Handler) error { return err } + // Serve status of `_redirects` under `_redirects` + // We check if the final resolved path is `_redirects` after symlink traversal + if fullPath == redirects.ConfigFile { + if os.Getenv("FF_ENABLE_REDIRECTS") == "true" { + r := redirects.ParseRedirects(ctx, root) + return reader.serveRedirectsStatus(h, r) + } + + h.Writer.WriteHeader(http.StatusForbidden) + return nil + } + return reader.serveFile(ctx, h.Writer, h.Request, root, fullPath, h.LookupPath.HasAccessControl) } diff --git a/internal/serving/disk/serving.go b/internal/serving/disk/serving.go index f95f983c..bb9b40d2 100644 --- a/internal/serving/disk/serving.go +++ b/internal/serving/disk/serving.go @@ -1,6 +1,8 @@ package disk import ( + "os" + "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors" "gitlab.com/gitlab-org/gitlab-pages/internal/serving" "gitlab.com/gitlab-org/gitlab-pages/internal/vfs" @@ -15,7 +17,17 @@ type Disk struct { // ServeFileHTTP serves a file from disk and returns true. It returns false // when a file could not been found. func (s *Disk) ServeFileHTTP(h serving.Handler) bool { - return s.reader.tryFile(h) == nil + if s.reader.tryFile(h) == nil { + return true + } + + if os.Getenv("FF_ENABLE_REDIRECTS") == "true" { + if s.reader.tryRedirects(h) == nil { + return true + } + } + + return false } // ServeNotFoundHTTP tries to read a custom 404 page diff --git a/internal/serving/disk/symlink/path_test.go b/internal/serving/disk/symlink/path_test.go index 23978037..8c1d19b3 100644 --- a/internal/serving/disk/symlink/path_test.go +++ b/internal/serving/disk/symlink/path_test.go @@ -16,28 +16,13 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk/symlink" + "gitlab.com/gitlab-org/gitlab-pages/internal/testhelpers" "gitlab.com/gitlab-org/gitlab-pages/internal/vfs" "gitlab.com/gitlab-org/gitlab-pages/internal/vfs/local" ) var fs = vfs.Instrumented(&local.VFS{}, "local") -func tmpDir(t *testing.T) (vfs.Root, string, func()) { - tmpDir, err := ioutil.TempDir("", "symlink_tests") - require.NoError(t, err) - - // On some systems `/tmp` can be a symlink - tmpDir, err = filepath.EvalSymlinks(tmpDir) - require.NoError(t, err) - - root, err := fs.Root(context.Background(), tmpDir) - require.NoError(t, err) - - return root, tmpDir, func() { - os.RemoveAll(tmpDir) - } -} - type EvalSymlinksTest struct { // If dest is empty, the path is created; otherwise the dest is symlinked to the path. path, dest string @@ -100,7 +85,7 @@ func testEvalSymlinks(t *testing.T, wd, path, want string) { } func TestEvalSymlinks(t *testing.T) { - _, tmpDir, cleanup := tmpDir(t) + _, tmpDir, cleanup := testhelpers.TmpDir(t, "symlink_tests") defer cleanup() // Create the symlink farm using relative paths. @@ -139,7 +124,7 @@ func TestEvalSymlinks(t *testing.T) { } func TestEvalSymlinksIsNotExist(t *testing.T) { - root, _, cleanup := tmpDir(t) + root, _, cleanup := testhelpers.TmpDir(t, "symlink_tests") defer cleanup() _, err := symlink.EvalSymlinks(context.Background(), root, "notexist") @@ -160,7 +145,7 @@ func TestEvalSymlinksIsNotExist(t *testing.T) { } func TestIssue13582(t *testing.T) { - root, tmpDir, cleanup := tmpDir(t) + root, tmpDir, cleanup := testhelpers.TmpDir(t, "symlink_tests") defer cleanup() dir := filepath.Join(tmpDir, "dir") |