diff --git a/modules/caddyhttp/fileserver/matcher_test.go b/modules/caddyhttp/fileserver/matcher_test.go index 36483fcd9..4342d5d31 100644 --- a/modules/caddyhttp/fileserver/matcher_test.go +++ b/modules/caddyhttp/fileserver/matcher_test.go @@ -20,7 +20,9 @@ import ( "net/http/httptest" "net/url" "os" + "path/filepath" "runtime" + "strings" "testing" "github.com/caddyserver/caddy/v2" @@ -28,6 +30,13 @@ import ( "github.com/caddyserver/caddy/v2/modules/caddyhttp" ) +type testCase struct { + path string + expectedPath string + expectedType string + matched bool +} + func TestFileMatcher(t *testing.T) { // Windows doesn't like colons in files names isWindows := runtime.GOOS == "windows" @@ -45,12 +54,7 @@ func TestFileMatcher(t *testing.T) { f.Close() } - for i, tc := range []struct { - path string - expectedPath string - expectedType string - matched bool - }{ + for i, tc := range []testCase{ { path: "/foo.txt", expectedPath: "/foo.txt", @@ -115,51 +119,72 @@ func TestFileMatcher(t *testing.T) { expectedType: "file", matched: !isWindows, }, - { - path: "/foodir/secr%5Cet.txt", - expectedPath: "/foodir/secr\\et.txt", - expectedType: "file", - matched: true, - }, } { - m := &MatchFile{ - fsmap: &filesystems.FileSystemMap{}, - Root: "./testdata", - TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/"}, - } + fileMatcherTest(t, i, tc) + } +} - u, err := url.Parse(tc.path) - if err != nil { - t.Errorf("Test %d: parsing path: %v", i, err) - } +func TestFileMatcherNonWindows(t *testing.T) { + if runtime.GOOS == "windows" { + return + } - req := &http.Request{URL: u} - repl := caddyhttp.NewTestReplacer(req) + // this is impossible to test on Windows, but tests a security patch for other platforms + tc := testCase{ + path: "/foodir/secr%5Cet.txt", + expectedPath: "/foodir/secr\\et.txt", + expectedType: "file", + matched: true, + } - result, err := m.MatchWithError(req) - if err != nil { - t.Errorf("Test %d: unexpected error: %v", i, err) - } - if result != tc.matched { - t.Errorf("Test %d: expected match=%t, got %t", i, tc.matched, result) - } + f, err := os.Create(filepath.Join("testdata", strings.TrimPrefix(tc.expectedPath, "/"))) + if err != nil { + t.Fatalf("could not create test file: %v", err) + } + defer f.Close() + defer os.Remove(f.Name()) - rel, ok := repl.Get("http.matchers.file.relative") - if !ok && result { - t.Errorf("Test %d: expected replacer value", i) - } - if !result { - continue - } + fileMatcherTest(t, 0, tc) +} - if rel != tc.expectedPath { - t.Errorf("Test %d: actual path: %v, expected: %v", i, rel, tc.expectedPath) - } +func fileMatcherTest(t *testing.T, i int, tc testCase) { + m := &MatchFile{ + fsmap: &filesystems.FileSystemMap{}, + Root: "./testdata", + TryFiles: []string{"{http.request.uri.path}", "{http.request.uri.path}/"}, + } - fileType, _ := repl.Get("http.matchers.file.type") - if fileType != tc.expectedType { - t.Errorf("Test %d: actual file type: %v, expected: %v", i, fileType, tc.expectedType) - } + u, err := url.Parse(tc.path) + if err != nil { + t.Errorf("Test %d: parsing path: %v", i, err) + } + + req := &http.Request{URL: u} + repl := caddyhttp.NewTestReplacer(req) + + result, err := m.MatchWithError(req) + if err != nil { + t.Errorf("Test %d: unexpected error: %v", i, err) + } + if result != tc.matched { + t.Errorf("Test %d: expected match=%t, got %t", i, tc.matched, result) + } + + rel, ok := repl.Get("http.matchers.file.relative") + if !ok && result { + t.Errorf("Test %d: expected replacer value", i) + } + if !result { + return + } + + if rel != tc.expectedPath { + t.Errorf("Test %d: actual path: %v, expected: %v", i, rel, tc.expectedPath) + } + + fileType, _ := repl.Get("http.matchers.file.type") + if fileType != tc.expectedType { + t.Errorf("Test %d: actual file type: %v, expected: %v", i, fileType, tc.expectedType) } } diff --git "a/modules/caddyhttp/fileserver/testdata/foodir/secr\\et.txt" "b/modules/caddyhttp/fileserver/testdata/foodir/secr\\et.txt" deleted file mode 100644 index e69de29bb..000000000