From 2f0005bf6496da4a419a3a4461f32f94ef1428b2 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 10 Feb 2026 18:38:54 -0800 Subject: [PATCH] Fix BaseURL.JoinPath encoding slashes in paths, add URL tests JoinPath used url.PathEscape on the entire path which encoded slashes as %2F. Now encodes each segment individually. Add tests for all URL types. --- mfer/url.go | 8 ++++++-- mfer/url_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 mfer/url_test.go diff --git a/mfer/url.go b/mfer/url.go index fb1da96..274687e 100644 --- a/mfer/url.go +++ b/mfer/url.go @@ -27,8 +27,12 @@ func (b BaseURL) JoinPath(path RelFilePath) (FileURL, error) { base.Path += "/" } - // Parse and encode the relative path - ref, err := url.Parse(url.PathEscape(string(path))) + // Encode each path segment individually to preserve slashes + segments := strings.Split(string(path), "/") + for i, seg := range segments { + segments[i] = url.PathEscape(seg) + } + ref, err := url.Parse(strings.Join(segments, "/")) if err != nil { return "", err } diff --git a/mfer/url_test.go b/mfer/url_test.go new file mode 100644 index 0000000..dd36a4a --- /dev/null +++ b/mfer/url_test.go @@ -0,0 +1,44 @@ +package mfer + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBaseURLJoinPath(t *testing.T) { + tests := []struct { + base BaseURL + path RelFilePath + expected string + }{ + {"https://example.com/dir/", "file.txt", "https://example.com/dir/file.txt"}, + {"https://example.com/dir", "file.txt", "https://example.com/dir/file.txt"}, + {"https://example.com/", "sub/file.txt", "https://example.com/sub/file.txt"}, + {"https://example.com/dir/", "file with spaces.txt", "https://example.com/dir/file%20with%20spaces.txt"}, + } + + for _, tt := range tests { + t.Run(string(tt.base)+"+"+string(tt.path), func(t *testing.T) { + result, err := tt.base.JoinPath(tt.path) + require.NoError(t, err) + assert.Equal(t, tt.expected, string(result)) + }) + } +} + +func TestBaseURLString(t *testing.T) { + b := BaseURL("https://example.com/") + assert.Equal(t, "https://example.com/", b.String()) +} + +func TestFileURLString(t *testing.T) { + f := FileURL("https://example.com/file.txt") + assert.Equal(t, "https://example.com/file.txt", f.String()) +} + +func TestManifestURLString(t *testing.T) { + m := ManifestURL("https://example.com/index.mf") + assert.Equal(t, "https://example.com/index.mf", m.String()) +}