Skip to content

Commit e87576b

Browse files
committed
Fix joined url.
1 parent a587d25 commit e87576b

File tree

2 files changed

+154
-35
lines changed

2 files changed

+154
-35
lines changed

modules/util/url.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package util
55

66
import (
77
"net/url"
8-
"path"
98
"strings"
109
)
1110

@@ -28,14 +27,21 @@ func URLJoin(base string, elems ...string) string {
2827
if err != nil {
2928
return ""
3029
}
31-
joinedPath := path.Join(elems...)
32-
argURL, err := url.Parse(joinedPath)
33-
if err != nil {
34-
return ""
30+
31+
var fragment string
32+
last := len(elems) - 1
33+
if len(elems) > 0 {
34+
if strings.Contains(elems[last], "#") {
35+
elems[last], fragment, _ = strings.Cut(elems[last], "#")
36+
}
37+
elems[last] = strings.TrimSuffix(elems[last], "/") // keep old behaviour
3538
}
36-
joinedURL := baseURL.ResolveReference(argURL).String()
39+
40+
joinedURL := baseURL.JoinPath(elems...)
41+
joinedURL.Fragment = fragment
42+
3743
if !baseURL.IsAbs() && !strings.HasPrefix(base, "/") {
38-
return joinedURL[1:] // Removing leading '/' if needed
44+
return strings.TrimPrefix(joinedURL.String(), "/") // Removing leading '/' if needed
3945
}
40-
return joinedURL
46+
return joinedURL.String()
4147
}

modules/util/util_test.go

Lines changed: 140 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,148 @@ import (
1313
)
1414

1515
func TestURLJoin(t *testing.T) {
16-
type test struct {
17-
Expected string
16+
cases := []struct {
1817
Base string
19-
Elements []string
20-
}
21-
newTest := func(expected, base string, elements ...string) test {
22-
return test{Expected: expected, Base: base, Elements: elements}
18+
Elems []string
19+
Expected string
20+
}{
21+
{
22+
Base: "https://try.gitea.io",
23+
Elems: []string{"a/b", "c"},
24+
Expected: "https://try.gitea.io/a/b/c",
25+
},
26+
{
27+
Base: "https://try.gitea.io/",
28+
Elems: []string{"a/b", "c"},
29+
Expected: "https://try.gitea.io/a/b/c",
30+
},
31+
{
32+
Base: "https://try.gitea.io/",
33+
Elems: []string{"/a/b/", "/c/"},
34+
Expected: "https://try.gitea.io/a/b/c",
35+
},
36+
{
37+
Base: "https://try.gitea.io/",
38+
Elems: []string{"/a/./b/", "../c/"},
39+
Expected: "https://try.gitea.io/a/c",
40+
},
41+
{
42+
Base: "a",
43+
Elems: []string{"b/c/"},
44+
Expected: "a/b/c",
45+
},
46+
{
47+
Base: "a/",
48+
Elems: []string{"b/c/", "/../d/"},
49+
Expected: "a/b/d",
50+
},
51+
{
52+
Base: "https://try.gitea.io",
53+
Elems: []string{"a/b", "c#d"},
54+
Expected: "https://try.gitea.io/a/b/c#d",
55+
},
56+
{
57+
Base: "/a/",
58+
Elems: []string{"b/c/", "/../d/"},
59+
Expected: "/a/b/d",
60+
},
61+
{
62+
Base: "/a",
63+
Elems: []string{"b/c/"},
64+
Expected: "/a/b/c",
65+
},
66+
{
67+
Base: "/a",
68+
Elems: []string{"b/c#hash"},
69+
Expected: "/a/b/c#hash",
70+
},
71+
{
72+
Base: "\x7f", // invalid url
73+
Expected: "",
74+
},
75+
{
76+
Base: "path",
77+
Expected: "path/",
78+
},
79+
{
80+
Base: "/path",
81+
Expected: "/path/",
82+
},
83+
{
84+
Base: "path/",
85+
Expected: "path/",
86+
},
87+
{
88+
Base: "/path/",
89+
Expected: "/path/",
90+
},
91+
{
92+
Base: "path",
93+
Elems: []string{"sub"},
94+
Expected: "path/sub",
95+
},
96+
{
97+
Base: "/path",
98+
Elems: []string{"sub"},
99+
Expected: "/path/sub",
100+
},
101+
{
102+
Base: "https://gitea.com",
103+
Expected: "https://gitea.com/",
104+
},
105+
{
106+
Base: "https://gitea.com/",
107+
Expected: "https://gitea.com/",
108+
},
109+
{
110+
Base: "https://gitea.com",
111+
Elems: []string{"sub/path"},
112+
Expected: "https://gitea.com/sub/path",
113+
},
114+
{
115+
Base: "https://gitea.com/",
116+
Elems: []string{"sub", "path"},
117+
Expected: "https://gitea.com/sub/path",
118+
},
119+
{
120+
Base: "https://gitea.com/",
121+
Elems: []string{"sub", "..", "path"},
122+
Expected: "https://gitea.com/path",
123+
},
124+
{
125+
Base: "https://gitea.com/",
126+
Elems: []string{"sub/..", "path"},
127+
Expected: "https://gitea.com/path",
128+
},
129+
{
130+
Base: "https://gitea.com/",
131+
Elems: []string{"sub", "../path"},
132+
Expected: "https://gitea.com/path",
133+
},
134+
{
135+
Base: "https://gitea.com/",
136+
Elems: []string{"sub/../path"},
137+
Expected: "https://gitea.com/path",
138+
},
139+
{
140+
Base: "https://gitea.com/",
141+
Elems: []string{"sub", ".", "path"},
142+
Expected: "https://gitea.com/sub/path",
143+
},
144+
{
145+
Base: "https://gitea.com/",
146+
Elems: []string{"sub", "/", "path"},
147+
Expected: "https://gitea.com/sub/path",
148+
},
149+
{ // https://github.com/go-gitea/gitea/issues/25632
150+
Base: "/owner/repo/media/branch/main",
151+
Elems: []string{"/../other/image.png"},
152+
Expected: "/owner/repo/media/branch/other/image.png",
153+
},
23154
}
24-
for _, test := range []test{
25-
newTest("https://try.gitea.io/a/b/c",
26-
"https://try.gitea.io", "a/b", "c"),
27-
newTest("https://try.gitea.io/a/b/c",
28-
"https://try.gitea.io/", "/a/b/", "/c/"),
29-
newTest("https://try.gitea.io/a/c",
30-
"https://try.gitea.io/", "/a/./b/", "../c/"),
31-
newTest("a/b/c",
32-
"a", "b/c/"),
33-
newTest("a/b/d",
34-
"a/", "b/c/", "/../d/"),
35-
newTest("https://try.gitea.io/a/b/c#d",
36-
"https://try.gitea.io", "a/b", "c#d"),
37-
newTest("/a/b/d",
38-
"/a/", "b/c/", "/../d/"),
39-
newTest("/a/b/c",
40-
"/a", "b/c/"),
41-
newTest("/a/b/c#hash",
42-
"/a", "b/c#hash"),
43-
} {
44-
assert.Equal(t, test.Expected, URLJoin(test.Base, test.Elements...))
155+
156+
for i, c := range cases {
157+
assert.Equal(t, c.Expected, URLJoin(c.Base, c.Elems...), "Unexpected result in test case %v", i)
45158
}
46159
}
47160

0 commit comments

Comments
 (0)