diff --git a/modules/util/util.go b/modules/util/util.go index 3a0411f64b8..4bd2b843f73 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -7,6 +7,7 @@ package util import ( "net/url" "path" + "strings" "code.gitea.io/gitea/modules/log" ) @@ -56,16 +57,25 @@ func Max(a, b int) int { // URLJoin joins url components, like path.Join, but preserving contents func URLJoin(base string, elems ...string) string { - u, err := url.Parse(base) + if !strings.HasSuffix(base, "/") { + base += "/" + } + baseURL, err := url.Parse(base) if err != nil { log.Error(4, "URLJoin: Invalid base URL %s", base) return "" } - joinArgs := make([]string, 0, len(elems)+1) - joinArgs = append(joinArgs, u.Path) - joinArgs = append(joinArgs, elems...) - u.Path = path.Join(joinArgs...) - return u.String() + joinedPath := path.Join(elems...) + argURL, err := url.Parse(joinedPath) + if err != nil { + log.Error(4, "URLJoin: Invalid arg %s", joinedPath) + return "" + } + joinedURL := baseURL.ResolveReference(argURL).String() + if !baseURL.IsAbs() { + return joinedURL[1:] // Removing leading '/' + } + return joinedURL } // Min min of two ints diff --git a/modules/util/util_test.go b/modules/util/util_test.go index cc5875263a3..67d9efe1d2f 100644 --- a/modules/util/util_test.go +++ b/modules/util/util_test.go @@ -30,6 +30,8 @@ func TestURLJoin(t *testing.T) { "a", "b/c/"), newTest("a/b/d", "a/", "b/c/", "/../d/"), + newTest("https://try.gitea.io/a/b/c#d", + "https://try.gitea.io", "a/b", "c#d"), } { assert.Equal(t, test.Expected, URLJoin(test.Base, test.Elements...)) }