Skip to content

net/http/httputil: ReverseProxy should copy *req.URL #20068

Closed
@aronatkins

Description

@aronatkins

The ReverseProxy.ServeHTTP performs a shallow copy of the incoming request. This includes just copying the pointer of req.URL to outreq.URL. The director is likely to mutate that request URL, which can lead to mismatched pre/post logging.

Workaround: Copy the url.URL within a custom director.

What version of Go are you using (go version)?

go version go1.8.1 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/aron/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/ts/s940qvdj5vj1czr9qh07fvtw0000gn/T/go-build348823784=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

package main

import (
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

func main() {
	target, err := url.Parse("http://google.com/")
	if err != nil {
		log.Fatalf("could not parse URL: %s", err)
	}
	pxy := httputil.NewSingleHostReverseProxy(target)
	server := http.Server{
		Addr: ":9999",
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Printf("proxy starting: %s", r.URL)
			pxy.ServeHTTP(w, r)
			log.Printf("proxy complete: %s", r.URL)
		}),
	}
	err = server.ListenAndServe()
	if err != nil {
		log.Fatalf("could not serve: %s", err)
	}
}
$ curl http://localhost:9999/ > /dev/null

What did you expect to see?

2017/04/21 11:14:54 proxy starting: /
2017/04/21 11:14:54 proxy complete: /

What did you see instead?

2017/04/21 11:14:54 proxy starting: /
2017/04/21 11:14:54 proxy complete: http://google.com/

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions