From a83f9857d9bd51a942dc1aba73064df3ff8a3319 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Sat, 5 Dec 2020 00:11:13 +0800 Subject: [PATCH 1/9] support unix-abstract schema --- clientconn.go | 2 +- internal/grpcutil/target.go | 10 ++++++++-- internal/grpcutil/target_test.go | 8 ++++++++ internal/resolver/unix/unix.go | 23 ++++++++++++++++------- internal/transport/http2_client.go | 2 +- test/authority_test.go | 18 +++++++++++++++--- 6 files changed, 49 insertions(+), 14 deletions(-) diff --git a/clientconn.go b/clientconn.go index b35ba94f292d..2841614abab0 100644 --- a/clientconn.go +++ b/clientconn.go @@ -270,7 +270,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * cc.authority = creds.Info().ServerName } else if cc.dopts.insecure && cc.dopts.authority != "" { cc.authority = cc.dopts.authority - } else if strings.HasPrefix(cc.target, "unix:") { + } else if strings.HasPrefix(cc.target, "unix:") || strings.HasPrefix(cc.target, "unix-abstract:") { cc.authority = "localhost" } else if strings.HasPrefix(cc.parsedTarget.Endpoint, ":") { cc.authority = "localhost" + cc.parsedTarget.Endpoint diff --git a/internal/grpcutil/target.go b/internal/grpcutil/target.go index baa3479f12ca..bee858a4cb59 100644 --- a/internal/grpcutil/target.go +++ b/internal/grpcutil/target.go @@ -41,9 +41,15 @@ func split2(s, sep string) (string, string, bool) { // not parse "unix:[path]" cases. This should be true in cases where a custom // dialer is present, to prevent a behavior change. // -// If target is not a valid scheme://authority/endpoint, it returns {Endpoint: -// target}. +// If target is not valid dns/unix/unix-abstract schemas as specified in +// https://github.com/grpc/grpc/blob/master/doc/naming.md, +// it returns {Endpoint: target}. func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) { + if strings.HasPrefix(target, "unix-abstract:") { + // Handle unix-abstract case, split the target by ":" + scheme, endpoint, _ := split2(target, ":") + return resolver.Target{Scheme: scheme, Endpoint: endpoint} + } var ok bool ret.Scheme, ret.Endpoint, ok = split2(target, "://") if !ok { diff --git a/internal/grpcutil/target_test.go b/internal/grpcutil/target_test.go index 6083e84d75ae..e89f6daea81f 100644 --- a/internal/grpcutil/target_test.go +++ b/internal/grpcutil/target_test.go @@ -84,6 +84,14 @@ func TestParseTargetString(t *testing.T) { {targetStr: "unix:/a/b/c", want: resolver.Target{Scheme: "unix", Authority: "", Endpoint: "/a/b/c"}, wantWithDialer: resolver.Target{Scheme: "", Authority: "", Endpoint: "unix:/a/b/c"}}, {targetStr: "unix:///a/b/c", want: resolver.Target{Scheme: "unix", Authority: "", Endpoint: "/a/b/c"}}, + {targetStr: "unix-abstract:a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a/b/c"}}, + {targetStr: "unix-abstract:a b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a b"}}, + {targetStr: "unix-abstract:a:b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a:b"}}, + {targetStr: "unix-abstract:a-b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a-b"}}, + {targetStr: "unix-abstract:/ a///://::!@#$%^&*()b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/ a///://::!@#$%^&*()b"}}, + {targetStr: "unix-abstract:passthrough:abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "passthrough:abc"}}, + {targetStr: "unix-abstract:unix:///abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "unix:///abc"}}, + {targetStr: "passthrough:///unix:///a/b/c", want: resolver.Target{Scheme: "passthrough", Authority: "", Endpoint: "unix:///a/b/c"}}, } { got := ParseTarget(test.targetStr, false) diff --git a/internal/resolver/unix/unix.go b/internal/resolver/unix/unix.go index 8e78d47197c8..610c94758c86 100644 --- a/internal/resolver/unix/unix.go +++ b/internal/resolver/unix/unix.go @@ -26,20 +26,28 @@ import ( "google.golang.org/grpc/resolver" ) -const scheme = "unix" +const unixScheme = "unix" +const unixAbstractScheme = "unix-abstract" -type builder struct{} +type builder struct{ + scheme string +} -func (*builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { +func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { if target.Authority != "" { return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority) } - cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(resolver.Address{Addr: target.Endpoint}, "unix")}}) + addr := resolver.Address{Addr: target.Endpoint} + if b.scheme == unixAbstractScheme { + // prepend "\x00" to address for unix-abstract + addr.Addr = "\x00" + addr.Addr + } + cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}}) return &nopResolver{}, nil } -func (*builder) Scheme() string { - return scheme +func (b *builder) Scheme() string { + return b.scheme } type nopResolver struct { @@ -50,5 +58,6 @@ func (*nopResolver) ResolveNow(resolver.ResolveNowOptions) {} func (*nopResolver) Close() {} func init() { - resolver.Register(&builder{}) + resolver.Register(&builder{scheme: unixScheme}) + resolver.Register(&builder{scheme: unixAbstractScheme}) } diff --git a/internal/transport/http2_client.go b/internal/transport/http2_client.go index 4c9f9740ec71..e044722e3e79 100644 --- a/internal/transport/http2_client.go +++ b/internal/transport/http2_client.go @@ -143,7 +143,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error address := addr.Addr networkType, ok := networktype.Get(addr) if fn != nil { - if networkType == "unix" { + if networkType == "unix" && !strings.HasPrefix("\x00", address) { // For backward compatibility, if the user dialed "unix:///path", // the passthrough resolver would be used and the user's custom // dialer would see "unix:///path". Since the unix resolver is used diff --git a/test/authority_test.go b/test/authority_test.go index e6599b2fde04..09ba8c68ea08 100644 --- a/test/authority_test.go +++ b/test/authority_test.go @@ -23,6 +23,7 @@ import ( "fmt" "net" "os" + "strings" "sync" "testing" "time" @@ -53,8 +54,10 @@ func authorityChecker(ctx context.Context, expectedAuthority string) (*testpb.Em } func runUnixTest(t *testing.T, address, target, expectedAuthority string, dialer func(context.Context, string) (net.Conn, error)) { - if err := os.RemoveAll(address); err != nil { - t.Fatalf("Error removing socket file %v: %v\n", address, err) + if !strings.HasPrefix(target, "unix-abstract:") { + if err := os.RemoveAll(address); err != nil { + t.Fatalf("Error removing socket file %v: %v\n", address, err) + } } ss := &stubServer{ emptyCall: func(ctx context.Context, _ *testpb.Empty) (*testpb.Empty, error) { @@ -114,6 +117,13 @@ var authorityTests = []authorityTest{ authority: "unix:///tmp/sock.sock", dialTargetWant: "unix:///tmp/sock.sock", }, + { + name: "UnixAbstract", + address: "\x00abc efg", + target: "unix-abstract:abc efg", + authority: "localhost", + dialTargetWant: "\x00abc efg", + }, } // TestUnix does end to end tests with the various supported unix target @@ -139,7 +149,9 @@ func (s) TestUnixCustomDialer(t *testing.T) { if address != test.dialTargetWant { return nil, fmt.Errorf("expected target %v in custom dialer, instead got %v", test.dialTargetWant, address) } - address = address[len("unix:"):] + if !strings.HasPrefix(test.target, "unix-abstract:") { + address = address[len("unix:"):] + } return (&net.Dialer{}).DialContext(ctx, "unix", address) } runUnixTest(t, test.address, test.target, test.authority, dialer) From c3be95ebc5228c20b35c874118a6bfff6ed3b407 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Sat, 5 Dec 2020 00:49:51 +0800 Subject: [PATCH 2/9] go fmt --- internal/resolver/unix/unix.go | 2 +- test/authority_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/resolver/unix/unix.go b/internal/resolver/unix/unix.go index 610c94758c86..0d5a811ddfad 100644 --- a/internal/resolver/unix/unix.go +++ b/internal/resolver/unix/unix.go @@ -29,7 +29,7 @@ import ( const unixScheme = "unix" const unixAbstractScheme = "unix-abstract" -type builder struct{ +type builder struct { scheme string } diff --git a/test/authority_test.go b/test/authority_test.go index 09ba8c68ea08..f4e05cbaf875 100644 --- a/test/authority_test.go +++ b/test/authority_test.go @@ -118,10 +118,10 @@ var authorityTests = []authorityTest{ dialTargetWant: "unix:///tmp/sock.sock", }, { - name: "UnixAbstract", - address: "\x00abc efg", - target: "unix-abstract:abc efg", - authority: "localhost", + name: "UnixAbstract", + address: "\x00abc efg", + target: "unix-abstract:abc efg", + authority: "localhost", dialTargetWant: "\x00abc efg", }, } From 4fe4fa43287eee5a38aa828419c571dc385d9f2e Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Sat, 5 Dec 2020 01:08:21 +0800 Subject: [PATCH 3/9] fix test --- internal/transport/http2_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/transport/http2_client.go b/internal/transport/http2_client.go index e044722e3e79..8902b7f90d9d 100644 --- a/internal/transport/http2_client.go +++ b/internal/transport/http2_client.go @@ -143,7 +143,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error address := addr.Addr networkType, ok := networktype.Get(addr) if fn != nil { - if networkType == "unix" && !strings.HasPrefix("\x00", address) { + if networkType == "unix" && !strings.HasPrefix(address, "\x00") { // For backward compatibility, if the user dialed "unix:///path", // the passthrough resolver would be used and the user's custom // dialer would see "unix:///path". Since the unix resolver is used From 65dae86b13e437ba86a7dd129fb08d9eab065b01 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Sat, 5 Dec 2020 02:10:32 +0800 Subject: [PATCH 4/9] add unix-abstract support in http util --- internal/transport/http_util.go | 7 ++++++- internal/transport/http_util_test.go | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/transport/http_util.go b/internal/transport/http_util.go index 7e41d1183f93..5558019d8dd5 100644 --- a/internal/transport/http_util.go +++ b/internal/transport/http_util.go @@ -603,9 +603,14 @@ func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderList // parseDialTarget returns the network and address to pass to dialer. func parseDialTarget(target string) (string, string) { net := "tcp" + if strings.HasPrefix(target, "unix-abstract:") { + // handle unix-abstract:addr which will fail with url.Parse + // and need prepend "\x00" to the parsed address + return "unix", "\x00" + strings.SplitN(target, ":",2)[1] + } m1 := strings.Index(target, ":") m2 := strings.Index(target, ":/") - // handle unix:addr which will fail with url.Parse + // handle unix:addr which will fail with url.Parse if m1 >= 0 && m2 < 0 { if n := target[0:m1]; n == "unix" { return n, target[m1+1:] diff --git a/internal/transport/http_util_test.go b/internal/transport/http_util_test.go index 2205050acea0..5d7e9abdaf73 100644 --- a/internal/transport/http_util_test.go +++ b/internal/transport/http_util_test.go @@ -268,6 +268,10 @@ func (s) TestParseDialTarget(t *testing.T) { {"unix://domain", "unix", "domain"}, {"unix://etcd:0", "unix", "etcd:0"}, {"unix:///etcd:0", "unix", "/etcd:0"}, + {"unix-abstract:abc", "unix", "\x00abc"}, + {"unix-abstract:abc edf", "unix", "\x00abc edf"}, + {"unix-abstract:///abc", "unix", "\x00///abc"}, + {"unix-abstract:unix:abc", "unix", "\x00unix:abc"}, {"passthrough://unix://domain", "tcp", "passthrough://unix://domain"}, {"https://google.com:443", "tcp", "https://google.com:443"}, {"dns:///google.com", "tcp", "dns:///google.com"}, From a9733dce54c860517a0fcf39a0073999051da227 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Sat, 5 Dec 2020 02:13:24 +0800 Subject: [PATCH 5/9] go fmt --- internal/transport/http_util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/transport/http_util.go b/internal/transport/http_util.go index 5558019d8dd5..e4cd76a35455 100644 --- a/internal/transport/http_util.go +++ b/internal/transport/http_util.go @@ -606,11 +606,11 @@ func parseDialTarget(target string) (string, string) { if strings.HasPrefix(target, "unix-abstract:") { // handle unix-abstract:addr which will fail with url.Parse // and need prepend "\x00" to the parsed address - return "unix", "\x00" + strings.SplitN(target, ":",2)[1] + return "unix", "\x00" + strings.SplitN(target, ":", 2)[1] } m1 := strings.Index(target, ":") m2 := strings.Index(target, ":/") - // handle unix:addr which will fail with url.Parse + // handle unix:addr which will fail with url.Parse if m1 >= 0 && m2 < 0 { if n := target[0:m1]; n == "unix" { return n, target[m1+1:] From 80f52e757282b2116bc4bbcb8735883da3208bf0 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Fri, 11 Dec 2020 11:15:20 +0800 Subject: [PATCH 6/9] added more test case --- internal/grpcutil/target_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/grpcutil/target_test.go b/internal/grpcutil/target_test.go index e89f6daea81f..3409f9cdfc7f 100644 --- a/internal/grpcutil/target_test.go +++ b/internal/grpcutil/target_test.go @@ -91,6 +91,8 @@ func TestParseTargetString(t *testing.T) { {targetStr: "unix-abstract:/ a///://::!@#$%^&*()b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/ a///://::!@#$%^&*()b"}}, {targetStr: "unix-abstract:passthrough:abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "passthrough:abc"}}, {targetStr: "unix-abstract:unix:///abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "unix:///abc"}}, + {targetStr: "unix-abstract:///a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "///a/b/c"}}, + {targetStr: "unix-abstract://authority/a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "//authority/a/b/c"}}, {targetStr: "passthrough:///unix:///a/b/c", want: resolver.Target{Scheme: "passthrough", Authority: "", Endpoint: "unix:///a/b/c"}}, } { From f06e4ed09f3edbf32a81292572ac98a83654137c Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Fri, 11 Dec 2020 11:18:32 +0800 Subject: [PATCH 7/9] Revert "add unix-abstract support in http util" This reverts commit 65dae86b13e437ba86a7dd129fb08d9eab065b01. --- internal/transport/http_util.go | 5 ----- internal/transport/http_util_test.go | 4 ---- 2 files changed, 9 deletions(-) diff --git a/internal/transport/http_util.go b/internal/transport/http_util.go index e4cd76a35455..7e41d1183f93 100644 --- a/internal/transport/http_util.go +++ b/internal/transport/http_util.go @@ -603,11 +603,6 @@ func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderList // parseDialTarget returns the network and address to pass to dialer. func parseDialTarget(target string) (string, string) { net := "tcp" - if strings.HasPrefix(target, "unix-abstract:") { - // handle unix-abstract:addr which will fail with url.Parse - // and need prepend "\x00" to the parsed address - return "unix", "\x00" + strings.SplitN(target, ":", 2)[1] - } m1 := strings.Index(target, ":") m2 := strings.Index(target, ":/") // handle unix:addr which will fail with url.Parse diff --git a/internal/transport/http_util_test.go b/internal/transport/http_util_test.go index 5d7e9abdaf73..2205050acea0 100644 --- a/internal/transport/http_util_test.go +++ b/internal/transport/http_util_test.go @@ -268,10 +268,6 @@ func (s) TestParseDialTarget(t *testing.T) { {"unix://domain", "unix", "domain"}, {"unix://etcd:0", "unix", "etcd:0"}, {"unix:///etcd:0", "unix", "/etcd:0"}, - {"unix-abstract:abc", "unix", "\x00abc"}, - {"unix-abstract:abc edf", "unix", "\x00abc edf"}, - {"unix-abstract:///abc", "unix", "\x00///abc"}, - {"unix-abstract:unix:abc", "unix", "\x00unix:abc"}, {"passthrough://unix://domain", "tcp", "passthrough://unix://domain"}, {"https://google.com:443", "tcp", "https://google.com:443"}, {"dns:///google.com", "tcp", "dns:///google.com"}, From dc694834b17f690ec5deb34645c39e1202e40138 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Mon, 21 Dec 2020 11:41:58 +0800 Subject: [PATCH 8/9] parse authrity for unix-abstract schema and modify/add test cases --- internal/grpcutil/target.go | 63 ++++++++++++++++++++------------ internal/grpcutil/target_test.go | 6 ++- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/internal/grpcutil/target.go b/internal/grpcutil/target.go index bee858a4cb59..eecf4a7e9b92 100644 --- a/internal/grpcutil/target.go +++ b/internal/grpcutil/target.go @@ -45,31 +45,48 @@ func split2(s, sep string) (string, string, bool) { // https://github.com/grpc/grpc/blob/master/doc/naming.md, // it returns {Endpoint: target}. func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) { - if strings.HasPrefix(target, "unix-abstract:") { - // Handle unix-abstract case, split the target by ":" - scheme, endpoint, _ := split2(target, ":") - return resolver.Target{Scheme: scheme, Endpoint: endpoint} - } var ok bool - ret.Scheme, ret.Endpoint, ok = split2(target, "://") - if !ok { - if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing { - // Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases, - // because splitting on :// only handles the - // "unix://[/absolute/path]" case. Only handle if the dialer is nil, - // to avoid a behavior change with custom dialers. - return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]} + switch { + case strings.HasPrefix(target, "unix-abstract:"): + // unix-abstract schema + var remain string + if strings.HasPrefix(target, "unix-abstract://") { + // Maybe, with Authority specified, try to parse it + ret.Scheme, remain, _ = split2(target, "://") + ret.Authority, ret.Endpoint, ok = split2(remain, "/") + if !ok { + // No Authority, add the "//" back as Endpoint + ret.Endpoint = "//" + remain + } else { + // Found Authority, add the "/" back + ret.Endpoint = "/" + ret.Endpoint + } + } else { + // Without Authority specified, split target on ":" + ret.Scheme, ret.Endpoint, _ = split2(target, ":") + } + default: + // unix/dns schema + ret.Scheme, ret.Endpoint, ok = split2(target, "://") + if !ok { + if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing { + // Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases, + // because splitting on :// only handles the + // "unix://[/absolute/path]" case. Only handle if the dialer is nil, + // to avoid a behavior change with custom dialers. + return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]} + } + return resolver.Target{Endpoint: target} + } + ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") + if !ok { + return resolver.Target{Endpoint: target} + } + if ret.Scheme == "unix" { + // Add the "/" back in the unix case, so the unix resolver receives the + // actual endpoint in the "unix://[/absolute/path]" case. + ret.Endpoint = "/" + ret.Endpoint } - return resolver.Target{Endpoint: target} - } - ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") - if !ok { - return resolver.Target{Endpoint: target} - } - if ret.Scheme == "unix" { - // Add the "/" back in the unix case, so the unix resolver receives the - // actual endpoint in the "unix://[/absolute/path]" case. - ret.Endpoint = "/" + ret.Endpoint } return ret } diff --git a/internal/grpcutil/target_test.go b/internal/grpcutil/target_test.go index 3409f9cdfc7f..f6c586dd0808 100644 --- a/internal/grpcutil/target_test.go +++ b/internal/grpcutil/target_test.go @@ -91,8 +91,10 @@ func TestParseTargetString(t *testing.T) { {targetStr: "unix-abstract:/ a///://::!@#$%^&*()b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/ a///://::!@#$%^&*()b"}}, {targetStr: "unix-abstract:passthrough:abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "passthrough:abc"}}, {targetStr: "unix-abstract:unix:///abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "unix:///abc"}}, - {targetStr: "unix-abstract:///a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "///a/b/c"}}, - {targetStr: "unix-abstract://authority/a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "//authority/a/b/c"}}, + {targetStr: "unix-abstract:///a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/a/b/c"}}, + {targetStr: "unix-abstract://authority/a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "authority", Endpoint: "/a/b/c"}}, + {targetStr: "unix-abstract:///", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/"}}, + {targetStr: "unix-abstract://authority", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "//authority"}}, {targetStr: "passthrough:///unix:///a/b/c", want: resolver.Target{Scheme: "passthrough", Authority: "", Endpoint: "unix:///a/b/c"}}, } { From 7a68a45d07ef6e8ca56077641df50ab5be8214e8 Mon Sep 17 00:00:00 2001 From: Edmond Luo Date: Tue, 22 Dec 2020 17:27:10 +0800 Subject: [PATCH 9/9] code tune --- internal/grpcutil/target.go | 51 +++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/internal/grpcutil/target.go b/internal/grpcutil/target.go index eecf4a7e9b92..8833021da02e 100644 --- a/internal/grpcutil/target.go +++ b/internal/grpcutil/target.go @@ -41,21 +41,19 @@ func split2(s, sep string) (string, string, bool) { // not parse "unix:[path]" cases. This should be true in cases where a custom // dialer is present, to prevent a behavior change. // -// If target is not valid dns/unix/unix-abstract schemas as specified in +// If target is not a valid scheme://authority/endpoint as specified in // https://github.com/grpc/grpc/blob/master/doc/naming.md, // it returns {Endpoint: target}. func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) { var ok bool - switch { - case strings.HasPrefix(target, "unix-abstract:"): - // unix-abstract schema - var remain string + if strings.HasPrefix(target, "unix-abstract:") { if strings.HasPrefix(target, "unix-abstract://") { // Maybe, with Authority specified, try to parse it + var remain string ret.Scheme, remain, _ = split2(target, "://") ret.Authority, ret.Endpoint, ok = split2(remain, "/") if !ok { - // No Authority, add the "//" back as Endpoint + // No Authority, add the "//" back ret.Endpoint = "//" + remain } else { // Found Authority, add the "/" back @@ -65,28 +63,27 @@ func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) // Without Authority specified, split target on ":" ret.Scheme, ret.Endpoint, _ = split2(target, ":") } - default: - // unix/dns schema - ret.Scheme, ret.Endpoint, ok = split2(target, "://") - if !ok { - if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing { - // Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases, - // because splitting on :// only handles the - // "unix://[/absolute/path]" case. Only handle if the dialer is nil, - // to avoid a behavior change with custom dialers. - return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]} - } - return resolver.Target{Endpoint: target} - } - ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") - if !ok { - return resolver.Target{Endpoint: target} - } - if ret.Scheme == "unix" { - // Add the "/" back in the unix case, so the unix resolver receives the - // actual endpoint in the "unix://[/absolute/path]" case. - ret.Endpoint = "/" + ret.Endpoint + return ret + } + ret.Scheme, ret.Endpoint, ok = split2(target, "://") + if !ok { + if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing { + // Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases, + // because splitting on :// only handles the + // "unix://[/absolute/path]" case. Only handle if the dialer is nil, + // to avoid a behavior change with custom dialers. + return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]} } + return resolver.Target{Endpoint: target} + } + ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") + if !ok { + return resolver.Target{Endpoint: target} + } + if ret.Scheme == "unix" { + // Add the "/" back in the unix case, so the unix resolver receives the + // actual endpoint in the "unix://[/absolute/path]" case. + ret.Endpoint = "/" + ret.Endpoint } return ret }