Repository: grpc/grpc-go
File: internal/resolver/delegatingresolver/delegatingresolver.go (Go)

Code before:
	r.proxyResolver.Close()
	r.proxyResolver = nil
}

func needsProxyResolver(state *resolver.State) bool {
	for _, addr := range state.Addresses {
		if !skipProxy(addr) {
			return true
		}
	}
	for _, endpoint := range state.Endpoints {
		for _, addr := range endpoint.Addresses {
			if !skipProxy(addr) {
				return true
			}
		}
	}
	return false
}

func parseTarget(target string) (string, error) {
	if target == "" {
		return "", fmt.Errorf("missing address")
	}
	if host, port, err := net.SplitHostPort(target); err == nil {
		if port == "" {
			// If the port field is empty (target ends with colon), e.g. "[::1]:",
			// this is an error.
			return "", fmt.Errorf("missing port after port-separator colon")
		}
		// target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
		if host == "" {
			// Keep consistent with net.Dial(): If the host is empty, as in ":80",
			// the local system is assumed.
			host = "localhost"
		}
		return net.JoinHostPort(host, port), nil
	}
	if host, port, err := net.SplitHostPort(target + ":" + defaultPort); err == nil {
		// target doesn't have port
		return net.JoinHostPort(host, port), nil
	}
	return net.JoinHostPort(target, defaultPort), nil
}

func skipProxy(address resolver.Address) bool {
	// Avoid proxy when network is not tcp.
	networkType, ok := networktype.Get(address)
	if !ok {
		networkType, _ = transport.ParseDialTarget(address.Addr)
	}

Review comment (bug):
Based on the documentation of `net.SplitHostPort`, the `port` seems to be mandatory and it will return a `missing port in address` error in that case. So, I don't think we could have `err == nil` and `port == ""`. 

```
// SplitHostPort splits a network address of the form "host:port",
// "host%zone:port", "[host]:port" or "[host%zone]:port" into host or
// host%zone and port.
```

Please correct me if I'm wrong.

Code after:
	r.proxyResolver.Close()
	r.proxyResolver = nil
}

func needsProxyResolver(state *resolver.State) bool {
	for _, addr := range state.Addresses {
		if !skipProxy(addr) {
			return true
		}
	}
	for _, endpoint := range state.Endpoints {
		for _, addr := range endpoint.Addresses {
			if !skipProxy(addr) {
				return true
			}
		}
	}
	return false
}

// parseTarget takes a target string and ensures it is a valid "host:port" target.
//
// It does the following:
//  1. If the target already has a port (e.g., "host:port", "[ipv6]:port"),
//     it is returned as is.
//  2. If the host part is empty (e.g., ":80"), it defaults to "localhost",
//     returning "localhost:80".
//  3. If the target is missing a port (e.g., "host", "ipv6"), the defaultPort
//     is added.
//
// An error is returned for empty targets or targets with a trailing colon
// but no port (e.g., "host:").
func parseTarget(target string) (string, error) {
	if target == "" {
		return "", fmt.Errorf("missing address")
	}

	host, port, err := net.SplitHostPort(target)
	if err != nil {
		// If SplitHostPort fails, it's likely because the port is missing.
		// We append the default port and return the result.
		return net.JoinHostPort(target, defaultPort), nil
	}

	// If SplitHostPort succeeds, we check for edge cases.
	if port == "" {
		// A success with an empty port means the target had a trailing colon,
		// e.g., "host:", which is an error.
		return "", fmt.Errorf("missing port after port-separator colon")
	}
	if host == "" {