Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: net/url: add RelativeURLPath #22297

Closed
rogpeppe opened this issue Oct 16, 2017 · 9 comments
Closed

proposal: net/url: add RelativeURLPath #22297

rogpeppe opened this issue Oct 16, 2017 · 9 comments

Comments

@rogpeppe
Copy link
Contributor

We have url.URL.ResolveReference, but nothing to perform the reverse calculation:
calculating a relative path that will transform one URL path into another.
The calculation is not hard but it's tricky to get right, and a function to
do this seems like it would sit well inside the net/url package.

In all the places we've needed this so far, both the base and target paths
are within the same host, so a path-only calculation seems to work well
and saves a bunch of potential edge cases.

So I propose this addition to net/url:

// RelativeURLPath returns a relative URL path that is lexically
// equivalent to targpath when interpreted by url.URL.ResolveReference.
// That is, for a path x returned by RelativeURLPath(basePath, targPath),
// and a URL u with path basePath, u.Parse(x) will return a URL
// with path targPath.
//
// It is assumed that both basePath and targPath are normalized
// (have no . or .. elements).
//
// An error is returned if basePath or targPath are not absolute paths.
func RelativeURLPath(basePath, targPath string) (string, error)
@gopherbot gopherbot added this to the Proposal milestone Oct 16, 2017
@mvdan
Copy link
Member

mvdan commented Oct 16, 2017

I assume your existing implementation is at https://github.com/juju/httputil/blob/master/relativeurl.go?

Also, since this func only takes paths, have you considered the path package instead? It wouldn't be paired with its counterpart ResolveReference, but I wonder if the func would be useful in any other context that would avoid having to import net/url.

@rogpeppe
Copy link
Contributor Author

@mvdan I'm fairly sure that this wouldn't be useful in any context other than HTTP. The logic is peculiar to the specific semantics used by relative URLs. For example, a trailing slash is significant.

@rsc
Copy link
Contributor

rsc commented Oct 16, 2017

ResolveReference takes two *URL and returns a *URL.
Why does this function work on strings instead of *URLs?
It seems like it should match ResolveReference if it is the inverse.

url.Relative seems OK to me.

@ianlancetaylor
Copy link
Contributor

Ping @rogpeppe; see @rsc's comment above.

@bradfitz
Copy link
Contributor

bradfitz commented Apr 2, 2018

Or if it's two *url.URLs as arguments, it could be a method named "Sub" like https://golang.org/pkg/time/#Time.Sub

@rsc
Copy link
Contributor

rsc commented Apr 2, 2018

We have

func (base *URL) ResolveReference(ref *URL) (abs *URL)

We could add

func (base *URL) Relative(abs *URL) (ref *URL)

or

func (abs *URL) Relative(base *URL) (ref *URL)

It's unclear to me which people would expect.

Filepath has

func Rel(base, targ string) (rel string)

@rsc
Copy link
Contributor

rsc commented Apr 9, 2018

Does anyone want to make a case for why this is important? We often want relative file paths, for example to display to users, but it's pretty rare to insist on relative URLs. Pretty much all URL uses are fine as absolute URLs.

@rogpeppe
Copy link
Contributor Author

We needed this because we have some HTTP services that are behind an apache gateway that rewrites URL paths to add a prefix (so we have several hosted services under the same virtual host).

The problem is that it's not possible for a service to form a link to an absolute path within that service, because that might be wrong (it's also possible to reach the service without going through the apache proxy).

So we need to use relative links - hence this function (which was non-trivial to get right FWIW).

@rsc
Copy link
Contributor

rsc commented Apr 16, 2018

Thanks for the context @rogpeppe. For now it seems like this would be best outside the standard library - the need seems very specific and rare.

@rsc rsc closed this as completed Apr 16, 2018
@golang golang locked and limited conversation to collaborators Apr 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants