From d8544f1ea6000a23980e6c5b3a3d71131d3149a5 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 27 Nov 2022 14:21:36 +0200 Subject: [PATCH 1/2] client.go Make addMissingPort() public It's needed for those who creates the instance of the HostClient manually. --- client.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index c058f36004..c143dfbde8 100644 --- a/client.go +++ b/client.go @@ -495,7 +495,7 @@ func (c *Client) Do(req *Request, resp *Response) error { hc := m[string(host)] if hc == nil { hc = &HostClient{ - Addr: addMissingPort(string(host), isTLS), + Addr: AddMissingPort(string(host), isTLS), Name: c.Name, NoDefaultUserAgentHeader: c.NoDefaultUserAgentHeader, Dial: c.Dial, @@ -1968,7 +1968,7 @@ func dialAddr(addr string, dial DialFunc, dialDualStack, isTLS bool, tlsConfig * } else { dial = Dial } - addr = addMissingPort(addr, isTLS) + addr = AddMissingPort(addr, isTLS) } conn, err := dial(addr) if err != nil { @@ -2006,7 +2006,10 @@ func (c *HostClient) getClientName() []byte { return clientName } -func addMissingPort(addr string, isTLS bool) string { +// AddMissingPort adds a port to a host if it is missing. +// A literal IPv6 address in hostport must be enclosed in square +// brackets, as in "[::1]:80", "[::1%lo0]:80". +func AddMissingPort(addr string, isTLS bool) string { n := strings.Index(addr, ":") if n >= 0 { return addr From dee56b7151c930dc38ce1b9998b526e93a498672 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 27 Nov 2022 14:41:47 +0200 Subject: [PATCH 2/2] client.go fix AddMissingPort() Previously for IPv6 addresses the default port wasn't added. The fix adding a test and optimization that should avoid itoa() call and reduce a memory usage --- client.go | 25 ++++++++++++++++----- client_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index c143dfbde8..2b6b60f768 100644 --- a/client.go +++ b/client.go @@ -9,7 +9,6 @@ import ( "fmt" "io" "net" - "strconv" "strings" "sync" "sync/atomic" @@ -2010,15 +2009,29 @@ func (c *HostClient) getClientName() []byte { // A literal IPv6 address in hostport must be enclosed in square // brackets, as in "[::1]:80", "[::1%lo0]:80". func AddMissingPort(addr string, isTLS bool) string { - n := strings.Index(addr, ":") - if n >= 0 { + addrLen := len(addr) + if addrLen == 0 { return addr } - port := 80 + + isIp6 := addr[0] == '[' + if isIp6 { + // if the IPv6 has opening bracket but closing bracket is the last char then it doesn't have a port + isIp6WithoutPort := addr[addrLen-1] == ']' + if !isIp6WithoutPort { + return addr + } + } else { // IPv4 + columnPos := strings.LastIndexByte(addr, ':') + if columnPos > 0 { + return addr + } + } + port := ":80" if isTLS { - port = 443 + port = ":443" } - return net.JoinHostPort(addr, strconv.Itoa(port)) + return addr + port } // A wantConn records state about a wanted connection diff --git a/client_test.go b/client_test.go index 13da521033..b5c0b7f9ca 100644 --- a/client_test.go +++ b/client_test.go @@ -2971,3 +2971,63 @@ func TestHttpsRequestWithoutParsedURL(t *testing.T) { t.Fatal("https requests with IsTLS client must succeed") } } + +func Test_AddMissingPort(t *testing.T) { + type args struct { + addr string + isTLS bool + } + tests := []struct { + name string + args args + want string + }{ + { + args: args{"127.1", false}, // 127.1 is a short form of 127.0.0.1 + want: "127.1:80", + }, + { + args: args{"127.0.0.1", false}, + want: "127.0.0.1:80", + }, + { + args: args{"127.0.0.1", true}, + want: "127.0.0.1:443", + }, + { + args: args{"[::1]", false}, + want: "[::1]:80", + }, + { + args: args{"::1", false}, + want: "::1", // keep as is + }, + { + args: args{"[::1]", true}, + want: "[::1]:443", + }, + { + args: args{"127.0.0.1:8080", false}, + want: "127.0.0.1:8080", + }, + { + args: args{"127.0.0.1:8443", true}, + want: "127.0.0.1:8443", + }, + { + args: args{"[::1]:8080", false}, + want: "[::1]:8080", + }, + { + args: args{"[::1]:8443", true}, + want: "[::1]:8443", + }, + } + for _, tt := range tests { + t.Run(tt.want, func(t *testing.T) { + if got := AddMissingPort(tt.args.addr, tt.args.isTLS); got != tt.want { + t.Errorf("AddMissingPort() = %v, want %v", got, tt.want) + } + }) + } +}