@@ -1818,6 +1818,61 @@ func parseTarget(target string) (resolver.Target, error) {
18181818 return resolver.Target {URL : * u }, nil
18191819}
18201820
1821+ func encodeAuthority (authority string ) string {
1822+ const upperhex = "0123456789ABCDEF"
1823+
1824+ // Return for characters that must be escaped as per
1825+ // Valid chars are mentioned here:
1826+ // https://datatracker.ietf.org/doc/html/rfc3986#section-3.2
1827+ shouldEscape := func (c byte ) bool {
1828+ // Alphanum are always allowed.
1829+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
1830+ return false
1831+ }
1832+ switch c {
1833+ case '-' , '_' , '.' , '~' : // Unreserved characters
1834+ return false
1835+ case '!' , '$' , '&' , '\'' , '(' , ')' , '*' , '+' , ',' , ';' , '=' : // Subdelim characters
1836+ return false
1837+ case ':' , '[' , ']' , '@' : // Authority related delimeters
1838+ return false
1839+ }
1840+ // Everything else must be escaped.
1841+ return true
1842+ }
1843+
1844+ hexCount := 0
1845+ for i := 0 ; i < len (authority ); i ++ {
1846+ c := authority [i ]
1847+ if shouldEscape (c ) {
1848+ hexCount ++
1849+ }
1850+ }
1851+
1852+ if hexCount == 0 {
1853+ return authority
1854+ }
1855+
1856+ required := len (authority ) + 2 * hexCount
1857+ t := make ([]byte , required )
1858+
1859+ j := 0
1860+ // This logic is a barebones version of escape in the go net/url library.
1861+ for i := 0 ; i < len (authority ); i ++ {
1862+ switch c := authority [i ]; {
1863+ case shouldEscape (c ):
1864+ t [j ] = '%'
1865+ t [j + 1 ] = upperhex [c >> 4 ]
1866+ t [j + 2 ] = upperhex [c & 15 ]
1867+ j += 3
1868+ default :
1869+ t [j ] = authority [i ]
1870+ j ++
1871+ }
1872+ }
1873+ return string (t )
1874+ }
1875+
18211876// Determine channel authority. The order of precedence is as follows:
18221877// - user specified authority override using `WithAuthority` dial option
18231878// - creds' notion of server name for the authentication handshake
@@ -1868,7 +1923,11 @@ func (cc *ClientConn) determineAuthority() error {
18681923 // the channel authority given the user's dial target. For resolvers
18691924 // which don't implement this interface, we will use the endpoint from
18701925 // "scheme://authority/endpoint" as the default authority.
1871- cc .authority = endpoint
1926+ // Escape the endpoint to handle use cases where the endpoint
1927+ // might not be a valid authority by default.
1928+ // For example an endpoint which has multiple paths like
1929+ // 'a/b/c', which is not a valid authority by default.
1930+ cc .authority = encodeAuthority (endpoint )
18721931 }
18731932 channelz .Infof (logger , cc .channelzID , "Channel authority set to %q" , cc .authority )
18741933 return nil
0 commit comments