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 '#'
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
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()
},
"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
{
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) {