fileserver: Fix tests on Windows

pull/7500/head
Matthew Holt 2026-02-20 11:46:45 -07:00
parent a1081194bf
commit cb436f0a0e
No known key found for this signature in database
2 changed files with 69 additions and 44 deletions

View File

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