Repository: go
Issue: net/http/httputil: document that ReverseProxy doesn't remove Alt-Svc header
Labels: Documentation,NeedsInvestigation

### What version of Go are you using (`go version`)?

<pre>
go version devel +27b9571de8 Fri Feb 22 19:30:43 2019 +0000 darwin/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>
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/ej/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/ej/gopath"
GOPROXY=""
GORACE=""
GOROOT="/Users/ej/go"
GOTMPDIR=""
GOTOOLDIR="/Users/ej/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/xh/6w5vj0s12y97yt81179m2ddm0000gq/T/go-build981855942=/tmp/go-build -gno-record-gcc-switches -fno-common"
</pre></details>

### What did you do?

When using `httputil.ReverseProxy`, the backend's `Alt-Svc` header is passed through to the original client. I do not believe it  should be. Passing this header back to the original client can cause the client to connect to some OTHER server, and not the reverse proxy on a future request. This is generally not the purpose.

The `httputil.ReverseProxy` attempts to remove all hop-by-hop headers. I *think* `Alt-Svc` header should be treated as a hop-by-hop header. From [RFC7838 Section 4](https://tools.ietf.org/html/rfc7838#section-4): "The ALTSVC frame is processed hop-by-hop".  Note this is about the *HTTP/2 ALTSVC* frame, and not the *HTTP/1.1 Alt-Svc* header. However, I believe it should be applied there as well.

Fixing this requires a one line addition to the `hopHeaders` slice: https://github.com/golang/go/blob/a14ed2a82a1563ba89e1f22ab517bf3c9abe416f/src/net/http/httputil/reverseproxy.go#L145

I'm happy to submit this change and a test if this is a good idea.

As an example, run this example proxy:

```go
package main

import (
	"flag"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

func main() {
	addr := flag.String("addr", "[::1]:8080", "listen addr")
	target := flag.String("target", "https://www.google.com/", "target backend")
	flag.Parse()

	parsedTarget, err := url.Parse(*target)
	if err != nil {
		panic(err)
	}

	// start a proxy that replaces everything before the path
	proxy := &httputil.ReverseProxy{
		Director: func(r *http.Request) {
			r.Host = ""
			r.URL.Scheme = parsedTarget.Scheme
			r.URL.Host = parsedTarget.Host
		},
	}

	log.Printf("listening on %s; proxying to %s\n", *addr, *target)
	err = http.ListenAndServe(*addr, proxy)
	if err != nil {
		panic(err)
	}
}
```

Then run `curl --verbose http://localhost:8080/` to make a request.


### What did you expect to see?

I would expect NOT to see the `Alt-Svc` header returned by the response.


### What did you see instead?

The original `Alt-Svc` header from Google's servers:

```
< HTTP/1.1 200 OK
< Alt-Svc: quic=":443"; ma=2592000; v="44,43,39"
...
```


### Related things

* Issue #18341 is discussing supporting HTTP Status 421 Misdirected Request. Issue #25804 is a timed out issue asking for http2 to support handling Alt-Svc. Both of these would allow ReverseProxy to handle this header internally, and are not related to removing it here.

* Caddy had an issue about this, and decided to strip it: https://github.com/mholt/caddy/issues/1051