From 91bd68cdc575c54931c7fdd0fda4834c5fe0445d Mon Sep 17 00:00:00 2001 From: Nicolas MASSE Date: Fri, 13 Nov 2020 20:33:22 +0100 Subject: [PATCH] fix bug in file:// url parsing --- url_checker.go | 24 ++++++++++++++++++++++-- url_checker_test.go | 5 ++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/url_checker.go b/url_checker.go index 8f40948..5ba19d8 100644 --- a/url_checker.go +++ b/url_checker.go @@ -9,6 +9,7 @@ import ( "path" "path/filepath" "regexp" + "strings" "sync" "time" @@ -93,13 +94,32 @@ func (c urlChecker) resolveURL(u string, f string) (string, bool, error) { return u, false, nil } + // The file URLs are a mess. According to the RFC, they should be like + // file://host/absolute/path/to/file or file:///absolute/path/to/file + // + // But in real life, the following form is accepted: + // file://relative/path/to/file + // + // To handle this special case, we have to parse the URL by ourself + p := uu.Path + if uu.Scheme == "file" { + if !strings.HasPrefix(u, "file://") { + return "", false, fmt.Errorf("wrong file URL syntax") + } + + p, err = url.PathUnescape(u[7:]) + if err != nil { + return "", false, err + } + } + if !path.IsAbs(uu.Path) { - return path.Join(filepath.Dir(f), uu.Path), true, nil + return path.Join(filepath.Dir(f), p), true, nil } if c.documentRoot == "" { return "", false, fmt.Errorf("document root directory is not specified") } - return path.Join(c.documentRoot, uu.Path), true, nil + return path.Join(c.documentRoot, p), true, nil } diff --git a/url_checker_test.go b/url_checker_test.go index cc3e861..1cd4ea7 100644 --- a/url_checker_test.go +++ b/url_checker_test.go @@ -41,9 +41,12 @@ func TestURLCheckerCheckLocal(t *testing.T) { assert.Equal(t, errSkipped, c.Check(u, "README.md")) } - for _, u := range []string{"README.md"} { + for _, u := range []string{"README.md", "file://README.md"} { assert.Equal(t, nil, c.Check(u, "README.md")) } + for _, u := range []string{"file://foo-bar-missing-file-azertyuiop"} { + assert.NotEqual(t, nil, c.Check(u, "README.md")) + } } func TestURLCheckerCheckWithTimeout(t *testing.T) {