@@ -21,6 +21,15 @@ import (
2121 "strings"
2222)
2323
24+ const (
25+ dnsScheme = "dns"
26+ unixScheme = "unix"
27+ unixAbstractScheme = "unix-abstract"
28+ vsockScheme = "vsock"
29+ httpScheme = "http"
30+ httpsScheme = "https"
31+ )
32+
2433// Parsed represents a parsed gRPC endpoint.
2534type Parsed struct {
2635 Target string
@@ -37,6 +46,7 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
3746 var hostname string
3847 var tls bool
3948
49+ noSchemeInEndpoint := false
4050 urlSplit := strings .Split (target , ":" )
4151 if len (urlSplit ) == 3 && ! strings .Contains (target , "://" ) {
4252 target = strings .Replace (target , ":" , "://" , 1 )
@@ -46,13 +56,14 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
4656 urlSplit = strings .Split (target , "://" )
4757 if len (urlSplit ) == 1 {
4858 target = "dns://" + target
59+ noSchemeInEndpoint = true
4960 } else {
5061 scheme := urlSplit [0 ]
5162 if ! schemeKnown (scheme ) {
5263 return Parsed {}, fmt .Errorf (("unknown scheme: %q" ), scheme )
5364 }
5465
55- if scheme == "dns" {
66+ if scheme == dnsScheme {
5667 urlSplit = strings .Split (target , "/" )
5768 if len (urlSplit ) < 4 {
5869 return Parsed {}, fmt .Errorf ("invalid dns scheme: %q" , target )
@@ -79,7 +90,7 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
7990 }
8091
8192 if ptarget .Query ().Has ("tls" ) {
82- if ptarget .Scheme == "http" || ptarget .Scheme == "https" {
93+ if ptarget .Scheme == httpScheme || ptarget .Scheme == httpsScheme {
8394 return Parsed {}, errors .New ("cannot use tls query parameter with http(s) scheme" )
8495 }
8596
@@ -92,11 +103,11 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
92103 }
93104
94105 scheme := ptarget .Scheme
95- if scheme == "https" {
106+ if scheme == httpsScheme {
96107 tls = true
97108 }
98- if scheme == "http" || scheme == "https" {
99- scheme = "dns"
109+ if scheme == httpScheme || scheme == httpsScheme {
110+ scheme = dnsScheme
100111 }
101112
102113 hostname = ptarget .Host
@@ -112,28 +123,28 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
112123 }
113124
114125 if len (hostname ) == 0 {
115- if scheme == "dns" {
126+ if scheme == dnsScheme {
116127 hostname = "localhost"
117128 } else {
118129 hostname = ptarget .Path
119130 }
120131 }
121132
122133 switch scheme {
123- case "unix" :
134+ case unixScheme :
124135 separator := ":"
125136 if strings .HasPrefix (endpoint , "unix://" ) {
126137 separator = "://"
127138 }
128139 target = scheme + separator + hostname
129140
130- case "vsock" :
141+ case vsockScheme :
131142 target = scheme + ":" + hostname + ":" + port
132143
133- case "unix-abstract" :
144+ case unixAbstractScheme :
134145 target = scheme + ":" + hostname
135146
136- case "dns" :
147+ case dnsScheme :
137148 if len (ptarget .Path ) > 0 {
138149 return Parsed {}, fmt .Errorf ("path is not allowed: %q" , ptarget .Path )
139150 }
@@ -142,9 +153,18 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
142153 hostname = "[" + hostname + "]"
143154 }
144155 if len (dnsAuthority ) > 0 {
145- dnsAuthority = "//" + dnsAuthority + "/"
156+ target = scheme + "://" + dnsAuthority + "/" + hostname + ":" + port
157+ } else if ptarget .Scheme == dnsScheme && ! noSchemeInEndpoint {
158+ // when real scheme is dns, keep the previous format (dns:hostname:port)
159+ target = scheme + ":" + hostname + ":" + port
160+ } else {
161+ // Use passthrough resolver (just host:port) instead of the dns: scheme.
162+ // In gRPC v1.78, targets of the form dns:host:port can be treated as
163+ // opaque by grpc.DialContext(), so the DNS resolver is not invoked.
164+ // Using a bare host:port target makes grpc.DialContext() fall back to
165+ // the passthrough resolver, which resolves and connects correctly.
166+ target = hostname + ":" + port
146167 }
147- target = scheme + ":" + dnsAuthority + hostname + ":" + port
148168
149169 default :
150170 return Parsed {}, fmt .Errorf ("unsupported scheme: %q" , scheme )
@@ -158,12 +178,12 @@ func ParseGRPCEndpoint(endpoint string) (Parsed, error) {
158178
159179func schemeKnown (scheme string ) bool {
160180 for _ , s := range []string {
161- "dns" ,
162- "unix" ,
163- "unix-abstract" ,
164- "vsock" ,
165- "http" ,
166- "https" ,
181+ dnsScheme ,
182+ unixScheme ,
183+ unixAbstractScheme ,
184+ vsockScheme ,
185+ httpScheme ,
186+ httpsScheme ,
167187 } {
168188 if scheme == s {
169189 return true
0 commit comments