mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
net/url: permit colons in the host of postgresql:// URLs
PostgreSQL's postgresql:// URL scheme permits a comma-separated list of host:ports to appear in the host subcomponent: https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS While this is not compliant with RFC 3986, it's something we've accepted for a long time. Continue to accept colons in the host when the URL scheme is "postgresql". Fixes #75859 Change-Id: Iaa2e82b0be11d8e034e10dd7f4d6070039acfa2c Reviewed-on: https://go-review.googlesource.com/c/go/+/722300 Reviewed-by: Roland Shoemaker <roland@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Sean Liao <sean@liao.dev>
This commit is contained in:
parent
a662badab9
commit
ff654ea100
2 changed files with 41 additions and 8 deletions
|
|
@ -489,7 +489,7 @@ func parse(rawURL string, viaRequest bool) (*URL, error) {
|
||||||
if i := strings.Index(authority, "/"); i >= 0 {
|
if i := strings.Index(authority, "/"); i >= 0 {
|
||||||
authority, rest = authority[:i], authority[i:]
|
authority, rest = authority[:i], authority[i:]
|
||||||
}
|
}
|
||||||
url.User, url.Host, err = parseAuthority(authority)
|
url.User, url.Host, err = parseAuthority(url.Scheme, authority)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -509,12 +509,12 @@ func parse(rawURL string, viaRequest bool) (*URL, error) {
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAuthority(authority string) (user *Userinfo, host string, err error) {
|
func parseAuthority(scheme, authority string) (user *Userinfo, host string, err error) {
|
||||||
i := strings.LastIndex(authority, "@")
|
i := strings.LastIndex(authority, "@")
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
host, err = parseHost(authority)
|
host, err = parseHost(scheme, authority)
|
||||||
} else {
|
} else {
|
||||||
host, err = parseHost(authority[i+1:])
|
host, err = parseHost(scheme, authority[i+1:])
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
|
@ -546,7 +546,7 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
|
||||||
|
|
||||||
// parseHost parses host as an authority without user
|
// parseHost parses host as an authority without user
|
||||||
// information. That is, as host[:port].
|
// information. That is, as host[:port].
|
||||||
func parseHost(host string) (string, error) {
|
func parseHost(scheme, host string) (string, error) {
|
||||||
if openBracketIdx := strings.LastIndex(host, "["); openBracketIdx != -1 {
|
if openBracketIdx := strings.LastIndex(host, "["); openBracketIdx != -1 {
|
||||||
// Parse an IP-Literal in RFC 3986 and RFC 6874.
|
// Parse an IP-Literal in RFC 3986 and RFC 6874.
|
||||||
// E.g., "[fe80::1]", "[fe80::1%25en0]", "[fe80::1]:80".
|
// E.g., "[fe80::1]", "[fe80::1%25en0]", "[fe80::1]:80".
|
||||||
|
|
@ -603,9 +603,22 @@ func parseHost(host string) (string, error) {
|
||||||
}
|
}
|
||||||
return "[" + unescapedHostname + "]" + unescapedColonPort, nil
|
return "[" + unescapedHostname + "]" + unescapedColonPort, nil
|
||||||
} else if i := strings.Index(host, ":"); i != -1 {
|
} else if i := strings.Index(host, ":"); i != -1 {
|
||||||
if j := strings.LastIndex(host, ":"); urlstrictcolons.Value() == "0" && j != i {
|
lastColon := strings.LastIndex(host, ":")
|
||||||
urlstrictcolons.IncNonDefault()
|
if lastColon != i {
|
||||||
i = j
|
if scheme == "postgresql" || scheme == "postgres" {
|
||||||
|
// PostgreSQL relies on non-RFC-3986 parsing to accept
|
||||||
|
// a comma-separated list of hosts (with optional ports)
|
||||||
|
// in the host subcomponent:
|
||||||
|
// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS
|
||||||
|
//
|
||||||
|
// Since we historically permitted colons to appear in the host,
|
||||||
|
// continue to permit it for postgres:// URLs only.
|
||||||
|
// https://go.dev/issue/75223
|
||||||
|
i = lastColon
|
||||||
|
} else if urlstrictcolons.Value() == "0" {
|
||||||
|
urlstrictcolons.IncNonDefault()
|
||||||
|
i = lastColon
|
||||||
|
}
|
||||||
}
|
}
|
||||||
colonPort := host[i:]
|
colonPort := host[i:]
|
||||||
if !validOptionalPort(colonPort) {
|
if !validOptionalPort(colonPort) {
|
||||||
|
|
|
||||||
|
|
@ -606,6 +606,26 @@ var urltests = []URLTest{
|
||||||
},
|
},
|
||||||
"mailto:?subject=hi",
|
"mailto:?subject=hi",
|
||||||
},
|
},
|
||||||
|
// PostgreSQL URLs can include a comma-separated list of host:post hosts.
|
||||||
|
// https://go.dev/issue/75859
|
||||||
|
{
|
||||||
|
"postgres://host1:1,host2:2,host3:3",
|
||||||
|
&URL{
|
||||||
|
Scheme: "postgres",
|
||||||
|
Host: "host1:1,host2:2,host3:3",
|
||||||
|
Path: "",
|
||||||
|
},
|
||||||
|
"postgres://host1:1,host2:2,host3:3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"postgresql://host1:1,host2:2,host3:3",
|
||||||
|
&URL{
|
||||||
|
Scheme: "postgresql",
|
||||||
|
Host: "host1:1,host2:2,host3:3",
|
||||||
|
Path: "",
|
||||||
|
},
|
||||||
|
"postgresql://host1:1,host2:2,host3:3",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// more useful string for debugging than fmt's struct printer
|
// more useful string for debugging than fmt's struct printer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue