Commit 1ff19201 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/url: add URL.Hostname and URL.Port accessors

Fixes #16142

Change-Id: I7609faaf00c69646b0bd44a60a63a22d9265feb0
Reviewed-on: https://go-review.googlesource.com/28933Reviewed-by: default avatarJoe Tsai <thebrokentoaster@gmail.com>
Reviewed-by: default avatarFrancesc Campoy Flores <campoy@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 6e87082d
...@@ -872,6 +872,7 @@ func resolvePath(base, ref string) string { ...@@ -872,6 +872,7 @@ func resolvePath(base, ref string) string {
} }
// IsAbs reports whether the URL is absolute. // IsAbs reports whether the URL is absolute.
// Absolute means that it has a non-empty scheme.
func (u *URL) IsAbs() bool { func (u *URL) IsAbs() bool {
return u.Scheme != "" return u.Scheme != ""
} }
...@@ -951,3 +952,43 @@ func (u *URL) RequestURI() string { ...@@ -951,3 +952,43 @@ func (u *URL) RequestURI() string {
} }
return result return result
} }
// Hostname returns u.Host, without any port number.
//
// If Host is an IPv6 literal with a port number, Hostname returns the
// IPv6 literal without the square brackets. IPv6 literals may include
// a zone identifier.
func (u *URL) Hostname() string {
return stripPort(u.Host)
}
// Port returns the port part of u.Host, without the leading colon.
// If u.Host doesn't contain a port, Port returns an empty string.
func (u *URL) Port() string {
return portOnly(u.Host)
}
func stripPort(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return hostport
}
if i := strings.IndexByte(hostport, ']'); i != -1 {
return strings.TrimPrefix(hostport[:i], "[")
}
return hostport[:colon]
}
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return ""
}
if i := strings.Index(hostport, "]:"); i != -1 {
return hostport[i+len("]:"):]
}
if strings.Contains(hostport, "]") {
return ""
}
return hostport[colon+len(":"):]
}
...@@ -1479,3 +1479,47 @@ func TestURLErrorImplementsNetError(t *testing.T) { ...@@ -1479,3 +1479,47 @@ func TestURLErrorImplementsNetError(t *testing.T) {
} }
} }
} }
func TestURLHostname(t *testing.T) {
tests := []struct {
host string // URL.Host field
want string
}{
{"foo.com:80", "foo.com"},
{"foo.com", "foo.com"},
{"FOO.COM", "FOO.COM"}, // no canonicalization (yet?)
{"1.2.3.4", "1.2.3.4"},
{"1.2.3.4:80", "1.2.3.4"},
{"[1:2:3:4]", "1:2:3:4"},
{"[1:2:3:4]:80", "1:2:3:4"},
{"[::1]:80", "::1"},
}
for _, tt := range tests {
u := &URL{Host: tt.host}
got := u.Hostname()
if got != tt.want {
t.Errorf("Hostname for Host %q = %q; want %q", tt.host, got, tt.want)
}
}
}
func TestURLPort(t *testing.T) {
tests := []struct {
host string // URL.Host field
want string
}{
{"foo.com", ""},
{"foo.com:80", "80"},
{"1.2.3.4", ""},
{"1.2.3.4:80", "80"},
{"[1:2:3:4]", ""},
{"[1:2:3:4]:80", "80"},
}
for _, tt := range tests {
u := &URL{Host: tt.host}
got := u.Port()
if got != tt.want {
t.Errorf("Port for Host %q = %q; want %q", tt.host, got, tt.want)
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment