Skip to content

Commit cbd0879

Browse files
committed
Merge branch 'master' into issue/24715/porting_go_to_freebsd_arm64
2 parents 9b3c5d2 + 61bb56a commit cbd0879

File tree

4 files changed

+69
-71
lines changed

4 files changed

+69
-71
lines changed

src/net/http/transport.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,8 @@ func resetProxyConfig() {
710710
}
711711

712712
func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
713+
// TODO: the validPort check is redundant after CL 189258, as url.URL.Port
714+
// only returns valid ports now. golang.org/issue/33600
713715
if port := treq.URL.Port(); !validPort(port) {
714716
return cm, fmt.Errorf("invalid URL port %q", port)
715717
}

src/net/http/transport_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4289,7 +4289,7 @@ func TestTransportRejectsAlphaPort(t *testing.T) {
42894289
t.Fatalf("got %#v; want *url.Error", err)
42904290
}
42914291
got := ue.Err.Error()
4292-
want := `invalid URL port "123foo"`
4292+
want := `invalid port ":123foo" after host`
42934293
if got != want {
42944294
t.Errorf("got error %q; want %q", got, want)
42954295
}

src/net/url/url.go

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,11 @@ func parseHost(host string) (string, error) {
648648
}
649649
return host1 + host2 + host3, nil
650650
}
651+
} else if i := strings.LastIndex(host, ":"); i != -1 {
652+
colonPort := host[i:]
653+
if !validOptionalPort(colonPort) {
654+
return "", fmt.Errorf("invalid port %q after host", colonPort)
655+
}
651656
}
652657

653658
var err error
@@ -1046,44 +1051,39 @@ func (u *URL) RequestURI() string {
10461051
return result
10471052
}
10481053

1049-
// Hostname returns u.Host, without any port number.
1054+
// Hostname returns u.Host, stripping any valid port number if present.
10501055
//
1051-
// If Host is an IPv6 literal with a port number, Hostname returns the
1052-
// IPv6 literal without the square brackets. IPv6 literals may include
1053-
// a zone identifier.
1056+
// If the result is enclosed in square brackets, as literal IPv6 addresses are,
1057+
// the square brackets are removed from the result.
10541058
func (u *URL) Hostname() string {
1055-
return stripPort(u.Host)
1059+
host, _ := splitHostPort(u.Host)
1060+
return host
10561061
}
10571062

10581063
// Port returns the port part of u.Host, without the leading colon.
1059-
// If u.Host doesn't contain a port, Port returns an empty string.
1064+
//
1065+
// If u.Host doesn't contain a valid numeric port, Port returns an empty string.
10601066
func (u *URL) Port() string {
1061-
return portOnly(u.Host)
1067+
_, port := splitHostPort(u.Host)
1068+
return port
10621069
}
10631070

1064-
func stripPort(hostport string) string {
1065-
colon := strings.IndexByte(hostport, ':')
1066-
if colon == -1 {
1067-
return hostport
1068-
}
1069-
if i := strings.IndexByte(hostport, ']'); i != -1 {
1070-
return strings.TrimPrefix(hostport[:i], "[")
1071-
}
1072-
return hostport[:colon]
1073-
}
1071+
// splitHostPort separates host and port. If the port is not valid, it returns
1072+
// the entire input as host, and it doesn't check the validity of the host.
1073+
// Unlike net.SplitHostPort, but per RFC 3986, it requires ports to be numeric.
1074+
func splitHostPort(hostport string) (host, port string) {
1075+
host = hostport
10741076

1075-
func portOnly(hostport string) string {
1076-
colon := strings.IndexByte(hostport, ':')
1077-
if colon == -1 {
1078-
return ""
1079-
}
1080-
if i := strings.Index(hostport, "]:"); i != -1 {
1081-
return hostport[i+len("]:"):]
1077+
colon := strings.LastIndexByte(host, ':')
1078+
if colon != -1 && validOptionalPort(host[colon:]) {
1079+
host, port = host[:colon], host[colon+1:]
10821080
}
1083-
if strings.Contains(hostport, "]") {
1084-
return ""
1081+
1082+
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
1083+
host = host[1 : len(host)-1]
10851084
}
1086-
return hostport[colon+len(":"):]
1085+
1086+
return
10871087
}
10881088

10891089
// Marshaling interface implementations.

src/net/url/url_test.go

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,10 @@ var urltests = []URLTest{
422422
},
423423
// worst case host, still round trips
424424
{
425-
"scheme://!$&'()*+,;=hello!:port/path",
425+
"scheme://!$&'()*+,;=hello!:1/path",
426426
&URL{
427427
Scheme: "scheme",
428-
Host: "!$&'()*+,;=hello!:port",
428+
Host: "!$&'()*+,;=hello!:1",
429429
Path: "/path",
430430
},
431431
"",
@@ -1425,11 +1425,13 @@ func TestParseErrors(t *testing.T) {
14251425
{"http://[::1]", false},
14261426
{"http://[::1]:80", false},
14271427
{"http://[::1]:namedport", true}, // rfc3986 3.2.3
1428+
{"http://x:namedport", true}, // rfc3986 3.2.3
14281429
{"http://[::1]/", false},
14291430
{"http://[::1]a", true},
14301431
{"http://[::1]%23", true},
14311432
{"http://[::1%25en0]", false}, // valid zone id
14321433
{"http://[::1]:", false}, // colon, but no port OK
1434+
{"http://x:", false}, // colon, but no port OK
14331435
{"http://[::1]:%38%30", true}, // not allowed: % encoding only for non-ASCII
14341436
{"http://[::1%25%41]", false}, // RFC 6874 allows over-escaping in zone
14351437
{"http://[%10::1]", true}, // no %xx escapes in IP address
@@ -1621,52 +1623,46 @@ func TestURLErrorImplementsNetError(t *testing.T) {
16211623
}
16221624
}
16231625

1624-
func TestURLHostname(t *testing.T) {
1626+
func TestURLHostnameAndPort(t *testing.T) {
16251627
tests := []struct {
1626-
host string // URL.Host field
1627-
want string
1628+
in string // URL.Host field
1629+
host string
1630+
port string
16281631
}{
1629-
{"foo.com:80", "foo.com"},
1630-
{"foo.com", "foo.com"},
1631-
{"FOO.COM", "FOO.COM"}, // no canonicalization (yet?)
1632-
{"1.2.3.4", "1.2.3.4"},
1633-
{"1.2.3.4:80", "1.2.3.4"},
1634-
{"[1:2:3:4]", "1:2:3:4"},
1635-
{"[1:2:3:4]:80", "1:2:3:4"},
1636-
{"[::1]:80", "::1"},
1637-
{"[::1]", "::1"},
1638-
{"localhost", "localhost"},
1639-
{"localhost:443", "localhost"},
1640-
{"some.super.long.domain.example.org:8080", "some.super.long.domain.example.org"},
1641-
{"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"},
1642-
{"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"},
1632+
{"foo.com:80", "foo.com", "80"},
1633+
{"foo.com", "foo.com", ""},
1634+
{"foo.com:", "foo.com", ""},
1635+
{"FOO.COM", "FOO.COM", ""}, // no canonicalization
1636+
{"1.2.3.4", "1.2.3.4", ""},
1637+
{"1.2.3.4:80", "1.2.3.4", "80"},
1638+
{"[1:2:3:4]", "1:2:3:4", ""},
1639+
{"[1:2:3:4]:80", "1:2:3:4", "80"},
1640+
{"[::1]:80", "::1", "80"},
1641+
{"[::1]", "::1", ""},
1642+
{"[::1]:", "::1", ""},
1643+
{"localhost", "localhost", ""},
1644+
{"localhost:443", "localhost", "443"},
1645+
{"some.super.long.domain.example.org:8080", "some.super.long.domain.example.org", "8080"},
1646+
{"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "17000"},
1647+
{"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ""},
1648+
1649+
// Ensure that even when not valid, Host is one of "Hostname",
1650+
// "Hostname:Port", "[Hostname]" or "[Hostname]:Port".
1651+
// See https://golang.org/issue/29098.
1652+
{"[google.com]:80", "google.com", "80"},
1653+
{"google.com]:80", "google.com]", "80"},
1654+
{"google.com:80_invalid_port", "google.com:80_invalid_port", ""},
1655+
{"[::1]extra]:80", "::1]extra", "80"},
1656+
{"google.com]extra:extra", "google.com]extra:extra", ""},
16431657
}
16441658
for _, tt := range tests {
1645-
u := &URL{Host: tt.host}
1646-
got := u.Hostname()
1647-
if got != tt.want {
1648-
t.Errorf("Hostname for Host %q = %q; want %q", tt.host, got, tt.want)
1659+
u := &URL{Host: tt.in}
1660+
host, port := u.Hostname(), u.Port()
1661+
if host != tt.host {
1662+
t.Errorf("Hostname for Host %q = %q; want %q", tt.in, host, tt.host)
16491663
}
1650-
}
1651-
}
1652-
1653-
func TestURLPort(t *testing.T) {
1654-
tests := []struct {
1655-
host string // URL.Host field
1656-
want string
1657-
}{
1658-
{"foo.com", ""},
1659-
{"foo.com:80", "80"},
1660-
{"1.2.3.4", ""},
1661-
{"1.2.3.4:80", "80"},
1662-
{"[1:2:3:4]", ""},
1663-
{"[1:2:3:4]:80", "80"},
1664-
}
1665-
for _, tt := range tests {
1666-
u := &URL{Host: tt.host}
1667-
got := u.Port()
1668-
if got != tt.want {
1669-
t.Errorf("Port for Host %q = %q; want %q", tt.host, got, tt.want)
1664+
if port != tt.port {
1665+
t.Errorf("Port for Host %q = %q; want %q", tt.in, port, tt.port)
16701666
}
16711667
}
16721668
}

0 commit comments

Comments
 (0)