Commit 899cd04e authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

net/http: add Request.RequestURI field

The new url.URL's parsing can be too canonicalizing for
certain applications. By keeping the original request URI
around, we give applications a gross escape hatch while
keeping the URL package clean and simple for normal uses.

(From a discussion with Gary Burd, Gustavo Niemeyer,
and Russ Cox.)

Fixes #2782

R=golang-dev, rsc, dsymonds
CC=golang-dev
https://golang.org/cl/5580044
parent 408f0b1f
...@@ -116,6 +116,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) { ...@@ -116,6 +116,10 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
return nil, errors.New("http: nil Request.URL") return nil, errors.New("http: nil Request.URL")
} }
if req.RequestURI != "" {
return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
}
// Most the callers of send (Get, Post, et al) don't need // Most the callers of send (Get, Post, et al) don't need
// Headers, leaving it uninitialized. We guarantee to the // Headers, leaving it uninitialized. We guarantee to the
// Transport that this has been initialized, though. // Transport that this has been initialized, though.
......
...@@ -428,3 +428,15 @@ func TestClientInsecureTransport(t *testing.T) { ...@@ -428,3 +428,15 @@ func TestClientInsecureTransport(t *testing.T) {
} }
} }
} }
func TestClientErrorWithRequestURI(t *testing.T) {
req, _ := NewRequest("GET", "http://localhost:1234/", nil)
req.RequestURI = "/this/field/is/illegal/and/should/error/"
_, err := DefaultClient.Do(req)
if err == nil {
t.Fatalf("expected an error")
}
if !strings.Contains(err.Error(), "RequestURI") {
t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
}
}
...@@ -64,6 +64,7 @@ var reqTests = []reqTest{ ...@@ -64,6 +64,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 7, ContentLength: 7,
Host: "www.techcrunch.com", Host: "www.techcrunch.com",
RequestURI: "http://www.techcrunch.com/",
}, },
"abcdef\n", "abcdef\n",
...@@ -89,6 +90,7 @@ var reqTests = []reqTest{ ...@@ -89,6 +90,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 0, ContentLength: 0,
Host: "foo.com", Host: "foo.com",
RequestURI: "/",
}, },
noBody, noBody,
...@@ -114,6 +116,7 @@ var reqTests = []reqTest{ ...@@ -114,6 +116,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 0, ContentLength: 0,
Host: "test", Host: "test",
RequestURI: "//user@host/is/actually/a/path/",
}, },
noBody, noBody,
...@@ -163,6 +166,7 @@ var reqTests = []reqTest{ ...@@ -163,6 +166,7 @@ var reqTests = []reqTest{
Header: Header{}, Header: Header{},
ContentLength: -1, ContentLength: -1,
Host: "foo.com", Host: "foo.com",
RequestURI: "/",
}, },
"foobar", "foobar",
...@@ -188,6 +192,7 @@ var reqTests = []reqTest{ ...@@ -188,6 +192,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 0, ContentLength: 0,
Host: "www.google.com:443", Host: "www.google.com:443",
RequestURI: "www.google.com:443",
}, },
noBody, noBody,
...@@ -211,6 +216,7 @@ var reqTests = []reqTest{ ...@@ -211,6 +216,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 0, ContentLength: 0,
Host: "127.0.0.1:6060", Host: "127.0.0.1:6060",
RequestURI: "127.0.0.1:6060",
}, },
noBody, noBody,
...@@ -234,6 +240,7 @@ var reqTests = []reqTest{ ...@@ -234,6 +240,7 @@ var reqTests = []reqTest{
Close: false, Close: false,
ContentLength: 0, ContentLength: 0,
Host: "", Host: "",
RequestURI: "/_goRPC_",
}, },
noBody, noBody,
......
...@@ -153,6 +153,12 @@ type Request struct { ...@@ -153,6 +153,12 @@ type Request struct {
// This field is ignored by the HTTP client. // This field is ignored by the HTTP client.
RemoteAddr string RemoteAddr string
// RequestURI is the unmodified Request-URI of the
// Request-Line (RFC 2616, Section 5.1) as sent by the client
// to a server. Usually the URL field should be used instead.
// It is an error to set this field in an HTTP client request.
RequestURI string
// TLS allows HTTP servers and other software to record // TLS allows HTTP servers and other software to record
// information about the TLS connection on which the request // information about the TLS connection on which the request
// was received. This field is not filled in by ReadRequest. // was received. This field is not filled in by ReadRequest.
...@@ -459,8 +465,8 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) { ...@@ -459,8 +465,8 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
if f = strings.SplitN(s, " ", 3); len(f) < 3 { if f = strings.SplitN(s, " ", 3); len(f) < 3 {
return nil, &badStringError{"malformed HTTP request", s} return nil, &badStringError{"malformed HTTP request", s}
} }
var rawurl string req.Method, req.RequestURI, req.Proto = f[0], f[1], f[2]
req.Method, rawurl, req.Proto = f[0], f[1], f[2] rawurl := req.RequestURI
var ok bool var ok bool
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok { if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
return nil, &badStringError{"malformed HTTP version", req.Proto} return nil, &badStringError{"malformed HTTP version", req.Proto}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment