mirror of https://github.com/golang/go.git
net/url: add OmitHost bool to url.URL
Previously, myscheme:/path and myscheme:///path were treated as the same URL although materially different. The distinction made clear by RFC 3986 sec. 5.3 where a different recomposition behavior is expected when a URI reference has an undefined host(authority) as in myscheme:/path vs. one with an empty host(authority) as in myscheme:///path. This change fixes the Parse/String roundtrip limitation for URLs with an undefined host and a single slash. Fixes #46059 Change-Id: I1b8d6042135513616374ff8c8dfb1cdb640f8efe Reviewed-on: https://go-review.googlesource.com/c/go/+/391294 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com> Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
3c2e73c8c3
commit
ab0f7611d7
|
|
@ -363,6 +363,7 @@ type URL struct {
|
|||
Host string // host or host:port
|
||||
Path string // path (relative paths may omit leading slash)
|
||||
RawPath string // encoded path hint (see EscapedPath method)
|
||||
OmitHost bool // do not emit empty host (authority)
|
||||
ForceQuery bool // append a query ('?') even if RawQuery is empty
|
||||
RawQuery string // encoded query values, without '?'
|
||||
Fragment string // fragment for references, without '#'
|
||||
|
|
@ -556,7 +557,12 @@ func parse(rawURL string, viaRequest bool) (*URL, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if url.Scheme != "" && strings.HasPrefix(rest, "/") {
|
||||
// OmitHost is set to true when rawURL has an empty host (authority).
|
||||
// See golang.org/issue/46059.
|
||||
url.OmitHost = true
|
||||
}
|
||||
|
||||
// Set Path and, optionally, RawPath.
|
||||
// RawPath is a hint of the encoding of Path. We don't want to set it if
|
||||
// the default escaping of Path is equivalent, to help make sure that people
|
||||
|
|
@ -806,15 +812,19 @@ func (u *URL) String() string {
|
|||
buf.WriteString(u.Opaque)
|
||||
} else {
|
||||
if u.Scheme != "" || u.Host != "" || u.User != nil {
|
||||
if u.Host != "" || u.Path != "" || u.User != nil {
|
||||
buf.WriteString("//")
|
||||
}
|
||||
if ui := u.User; ui != nil {
|
||||
buf.WriteString(ui.String())
|
||||
buf.WriteByte('@')
|
||||
}
|
||||
if h := u.Host; h != "" {
|
||||
buf.WriteString(escape(h, encodeHost))
|
||||
if u.OmitHost && u.Host == "" && u.User == nil {
|
||||
// omit empty host
|
||||
} else {
|
||||
if u.Host != "" || u.Path != "" || u.User != nil {
|
||||
buf.WriteString("//")
|
||||
}
|
||||
if ui := u.User; ui != nil {
|
||||
buf.WriteString(ui.String())
|
||||
buf.WriteByte('@')
|
||||
}
|
||||
if h := u.Host; h != "" {
|
||||
buf.WriteString(escape(h, encodeHost))
|
||||
}
|
||||
}
|
||||
}
|
||||
path := u.EscapedPath()
|
||||
|
|
|
|||
|
|
@ -163,14 +163,15 @@ var urltests = []URLTest{
|
|||
},
|
||||
"http:%2f%2fwww.google.com/?q=go+language",
|
||||
},
|
||||
// non-authority with path
|
||||
// non-authority with path; see golang.org/issue/46059
|
||||
{
|
||||
"mailto:/webmaster@golang.org",
|
||||
&URL{
|
||||
Scheme: "mailto",
|
||||
Path: "/webmaster@golang.org",
|
||||
Scheme: "mailto",
|
||||
Path: "/webmaster@golang.org",
|
||||
OmitHost: true,
|
||||
},
|
||||
"mailto:///webmaster@golang.org", // unfortunate compromise
|
||||
"",
|
||||
},
|
||||
// non-authority
|
||||
{
|
||||
|
|
@ -625,8 +626,8 @@ func ufmt(u *URL) string {
|
|||
pass = p
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawpath=%q, rawq=%q, frag=%q, rawfrag=%q, forcequery=%v",
|
||||
u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawPath, u.RawQuery, u.Fragment, u.RawFragment, u.ForceQuery)
|
||||
return fmt.Sprintf("opaque=%q, scheme=%q, user=%#v, pass=%#v, host=%q, path=%q, rawpath=%q, rawq=%q, frag=%q, rawfrag=%q, forcequery=%v, omithost=%t",
|
||||
u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawPath, u.RawQuery, u.Fragment, u.RawFragment, u.ForceQuery, u.OmitHost)
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue