http2: append query to :path pseudo-header

Change-Id: Id10c0a9a5652bc38d6ae324f160b41af95bbee7f
Reviewed-on: https://go-review.googlesource.com/16412
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/http2/transport.go b/http2/transport.go
index 46507aa..8472a11 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -617,14 +617,14 @@
 		host = req.URL.Host
 	}
 
-	path := req.URL.Path
-	if path == "" {
-		path = "/"
-	}
-
+	// 8.1.2.3 Request Pseudo-Header Fields
+	// The :path pseudo-header field includes the path and query parts of the
+	// target URI (the path-absolute production and optionally a '?' character
+	// followed by the query production (see Sections 3.3 and 3.4 of
+	// [RFC3986]).
 	cc.writeHeader(":authority", host) // probably not right for all sites
 	cc.writeHeader(":method", req.Method)
-	cc.writeHeader(":path", path)
+	cc.writeHeader(":path", req.URL.RequestURI())
 	cc.writeHeader(":scheme", "https")
 
 	for k, vv := range req.Header {
diff --git a/http2/transport_test.go b/http2/transport_test.go
index 8bbf60a..7439bae 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -11,6 +11,7 @@
 	"io/ioutil"
 	"net"
 	"net/http"
+	"net/url"
 	"os"
 	"reflect"
 	"strings"
@@ -167,6 +168,44 @@
 	}
 }
 
+// TODO: merge this with TestTransportBody to make TestTransportRequest? This
+// could be a table-driven test with extra goodies.
+func TestTransportPath(t *testing.T) {
+	gotc := make(chan *url.URL, 1)
+	st := newServerTester(t,
+		func(w http.ResponseWriter, r *http.Request) {
+			gotc <- r.URL
+		},
+		optOnlyServer,
+	)
+	defer st.Close()
+
+	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
+	defer tr.CloseIdleConnections()
+	const (
+		path  = "/testpath"
+		query = "q=1"
+	)
+	surl := st.ts.URL + path + "?" + query
+	req, err := http.NewRequest("POST", surl, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	c := &http.Client{Transport: tr}
+	res, err := c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	got := <-gotc
+	if got.Path != path {
+		t.Errorf("Read Path = %q; want %q", got.Path, path)
+	}
+	if got.RawQuery != query {
+		t.Errorf("Read RawQuery = %q; want %q", got.RawQuery, query)
+	}
+}
+
 func TestTransportBody(t *testing.T) {
 	gotc := make(chan interface{}, 1)
 	st := newServerTester(t,