'Combine URL paths with path.Join()
Is there a way in Go to combine URL paths similarly as we can do with filepaths using path.Join()?
For example see e.g. Combine absolute path and relative path to get a new absolute path.
When I use path.Join("http://foo", "bar"), I get http:/foo/bar.
See in Golang Playground.
Solution 1:[1]
ResolveReference() in net/url package
The accepted answer will not work for relative url paths containing file endings like .html or .img. The ResolveReference() function is the correct way to join url paths in go.
package main
import (
"fmt"
"log"
"net/url"
)
func main() {
u, err := url.Parse("../../..//search?q=dotnet")
if err != nil {
log.Fatal(err)
}
base, err := url.Parse("http://example.com/directory/")
if err != nil {
log.Fatal(err)
}
fmt.Println(base.ResolveReference(u))
}
Solution 2:[2]
A simple approach to this would be to trim the /'s you don't want and join. Here is an example func
func JoinURL(base string, paths ...string) string {
p := path.Join(paths...)
return fmt.Sprintf("%s/%s", strings.TrimRight(base, "/"), strings.TrimLeft(p, "/"))
}
Usage would be
b := "http://my.domain.com/api/"
u := JoinURL(b, "/foo", "bar/", "baz")
fmt.Println(u)
This removes the need for checking/returning errors
Solution 3:[3]
To join a URL with another URL or a path, there is URL.Parse():
func (u *URL) Parse(ref string) (*URL, error)Parse parses a URL in the context of the receiver. The provided URL may be relative or absolute. Parse returns
nil,erron parse failure, otherwise its return value is the same asResolveReference.
func TestURLParse(t *testing.T) {
baseURL, _ := url.Parse("http://foo/a/b/c")
url1, _ := baseURL.Parse("d/e")
require.Equal(t, "http://foo/a/b/d/e", url1.String())
url2, _ := baseURL.Parse("../d/e")
require.Equal(t, "http://foo/a/d/e", url2.String())
url3, _ := baseURL.Parse("/d/e")
require.Equal(t, "http://foo/d/e", url3.String())
}
Solution 4:[4]
In 1.19 there will be a new function in the standard library that solves this very neatly.
u := url.JoinPath("http://host/foo", "bar/")
Solution 5:[5]
I wrote this utility function that works for my purposes:
func Join(basePath string, paths ...string) (*url.URL, error) {
u, err := url.Parse(basePath)
if err != nil {
return nil, fmt.Errorf("invalid url")
}
p2 := append([]string{u.Path}, paths...)
result := path.Join(p2...)
u.Path = result
return u, nil
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | vbranden |
| Solution 3 | rustyx |
| Solution 4 | Mikael Frosthage |
| Solution 5 | Brent |
