Repository: go
Issue: x/net/http/httproxy: empty Host should bypass proxy
Labels: NeedsInvestigation

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.18.2 linux/amd64
</pre>

### Does this issue reproduce with the latest release?

Yes

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/ubuntu/.cache/go-build"
GOENV="/home/ubuntu/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/ubuntu/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/ubuntu/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/ubuntu/.local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/ubuntu/.local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/ubuntu/hello/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build736401068=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on go.dev/play is best.
-->

We are simulating a behavior where CoreDNS health plugin sends http requests via http_proxy to the `http://:8080/health` which is listened by the health plugin itself. We found that if we specify `http://127.0.0.1:8080/`, it won't connect to proxy, but only when we specify `http://:8080/health` it will always connect to proxy.

Sample code below which uses net/http with default transport, that mimics [CoreDNS overloaded function in health plugin](https://github.com/coredns/coredns/blob/v1.8.6/plugin/health/overloaded.go#L15), configure `export http_proxy=http://127.0.0.1:8000` before run:

```go
package main

import (
	"fmt"
	"net/http"
	"time"
)

func main() {
	timeout := time.Duration(3 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	// url := "http://127.0.0.1:8080/health" // not using proxy
	url := "http://:8080/health" // using proxy

	resp, err := client.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("succeed")
	resp.Body.Close()
}
```

### What did you expect to see?

`Get "http://:8080/health": dial tcp 127.0.0.1:8080: connect: connection refused` should show since it shouldn't reach proxy

### What did you see instead?

`Get "http://:8080/health": proxyconnect tcp: dial tcp 127.0.0.1:8000: connect: connection refused`

Note that [useProxy](https://cs.opensource.google/go/go/+/master:src/vendor/golang.org/x/net/http/httpproxy/proxy.go;l=186;drc=5f2fdbe7ed58bc98b60521bde2f3fcdc4af20826;bpv=1;bpt=1) function specifically checks "localhost" and loopback, does it make sense to also use proxy if hostname not provided?

See also: #1589 and #28866, note that in this scenario, it isn't possible to use no_proxy to exempt proxy usage, as no_proxy skips empty strings.