mirror of
https://github.com/golang/go
synced 2024-11-25 02:07:58 -07:00
http: remove finalURL from Client.Get; move to Response
This CL: -- removes Response.RequestMethod string -- adds Response.Request *Request -- removes the finalURL result parameter from client.Get() -- adds a gofix rule for callers of http.Get which assign the final url to the blank identifier; warning otherwise Caller who did: res, finalURL, err := http.Get(...) now need to do: res, err := http.Get(...) if err != nil { ... } finalURL := res.Request.URL.String() R=rsc CC=golang-dev https://golang.org/cl/4535056
This commit is contained in:
parent
4336116d3b
commit
05a1b7ec41
@ -37,7 +37,7 @@ func main() {
|
|||||||
b := strings.NewReader(*post)
|
b := strings.NewReader(*post)
|
||||||
r, err = http.Post(url, "application/x-www-form-urlencoded", b)
|
r, err = http.Post(url, "application/x-www-form-urlencoded", b)
|
||||||
} else {
|
} else {
|
||||||
r, _, err = http.Get(url)
|
r, err = http.Get(url)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -35,7 +35,7 @@ func dash(meth, cmd string, resp interface{}, args param) os.Error {
|
|||||||
}
|
}
|
||||||
cmd += "?" + http.EncodeQuery(m)
|
cmd += "?" + http.EncodeQuery(m)
|
||||||
}
|
}
|
||||||
r, _, err = http.Get(cmd)
|
r, err = http.Get(cmd)
|
||||||
case "POST":
|
case "POST":
|
||||||
r, err = http.PostForm(cmd, args)
|
r, err = http.PostForm(cmd, args)
|
||||||
default:
|
default:
|
||||||
|
@ -176,7 +176,7 @@ func remoteSearch(query string) (res *http.Response, err os.Error) {
|
|||||||
// remote search
|
// remote search
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
url := "http://" + addr + search
|
url := "http://" + addr + search
|
||||||
res, _, err = http.Get(url)
|
res, err = http.Get(url)
|
||||||
if err == nil && res.StatusCode == http.StatusOK {
|
if err == nil && res.StatusCode == http.StatusOK {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ GOFILES=\
|
|||||||
netdial.go\
|
netdial.go\
|
||||||
main.go\
|
main.go\
|
||||||
osopen.go\
|
osopen.go\
|
||||||
|
httpfinalurl.go\
|
||||||
httpserver.go\
|
httpserver.go\
|
||||||
procattr.go\
|
procattr.go\
|
||||||
reflect.go\
|
reflect.go\
|
||||||
|
56
src/cmd/gofix/httpfinalurl.go
Normal file
56
src/cmd/gofix/httpfinalurl.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
var httpFinalURLFix = fix{
|
||||||
|
"httpfinalurl",
|
||||||
|
httpfinalurl,
|
||||||
|
`Adapt http Get calls to not have a finalURL result parameter.
|
||||||
|
|
||||||
|
http://codereview.appspot.com/4535056/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
register(httpFinalURLFix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func httpfinalurl(f *ast.File) bool {
|
||||||
|
if !imports(f, "http") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fixed := false
|
||||||
|
walk(f, func(n interface{}) {
|
||||||
|
// Fix up calls to http.Get.
|
||||||
|
//
|
||||||
|
// If they have blank identifiers, remove them:
|
||||||
|
// resp, _, err := http.Get(url)
|
||||||
|
// -> resp, err := http.Get(url)
|
||||||
|
//
|
||||||
|
// But if they're using the finalURL parameter, warn:
|
||||||
|
// resp, finalURL, err := http.Get(url)
|
||||||
|
as, ok := n.(*ast.AssignStmt)
|
||||||
|
if !ok || len(as.Lhs) != 3 || len(as.Rhs) != 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isCall(as.Rhs[0], "http", "Get") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isBlank(as.Lhs[1]) {
|
||||||
|
as.Lhs = []ast.Expr{as.Lhs[0], as.Lhs[2]}
|
||||||
|
fixed = true
|
||||||
|
} else {
|
||||||
|
warn(as.Pos(), "call to http.Get records final URL")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return fixed
|
||||||
|
}
|
37
src/cmd/gofix/httpfinalurl_test.go
Normal file
37
src/cmd/gofix/httpfinalurl_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
addTestCases(httpfinalurlTests)
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpfinalurlTests = []testCase{
|
||||||
|
{
|
||||||
|
Name: "finalurl.0",
|
||||||
|
In: `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f() {
|
||||||
|
resp, _, err := http.Get("http://www.google.com/")
|
||||||
|
_, _ = resp, err
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
Out: `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f() {
|
||||||
|
resp, err := http.Get("http://www.google.com/")
|
||||||
|
_, _ = resp, err
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
@ -126,13 +126,10 @@ func shouldRedirect(statusCode int) bool {
|
|||||||
// 303 (See Other)
|
// 303 (See Other)
|
||||||
// 307 (Temporary Redirect)
|
// 307 (Temporary Redirect)
|
||||||
//
|
//
|
||||||
// finalURL is the URL from which the response was fetched -- identical to the
|
|
||||||
// input URL unless redirects were followed.
|
|
||||||
//
|
|
||||||
// Caller should close r.Body when done reading from it.
|
// Caller should close r.Body when done reading from it.
|
||||||
//
|
//
|
||||||
// Get is a convenience wrapper around DefaultClient.Get.
|
// Get is a convenience wrapper around DefaultClient.Get.
|
||||||
func Get(url string) (r *Response, finalURL string, err os.Error) {
|
func Get(url string) (r *Response, err os.Error) {
|
||||||
return DefaultClient.Get(url)
|
return DefaultClient.Get(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,11 +142,8 @@ func Get(url string) (r *Response, finalURL string, err os.Error) {
|
|||||||
// 303 (See Other)
|
// 303 (See Other)
|
||||||
// 307 (Temporary Redirect)
|
// 307 (Temporary Redirect)
|
||||||
//
|
//
|
||||||
// finalURL is the URL from which the response was fetched -- identical
|
|
||||||
// to the input URL unless redirects were followed.
|
|
||||||
//
|
|
||||||
// Caller should close r.Body when done reading from it.
|
// Caller should close r.Body when done reading from it.
|
||||||
func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
|
func (c *Client) Get(url string) (r *Response, err os.Error) {
|
||||||
// TODO: if/when we add cookie support, the redirected request shouldn't
|
// TODO: if/when we add cookie support, the redirected request shouldn't
|
||||||
// necessarily supply the same cookies as the original.
|
// necessarily supply the same cookies as the original.
|
||||||
var base *URL
|
var base *URL
|
||||||
@ -198,7 +192,6 @@ func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
|
|||||||
via = append(via, &req)
|
via = append(via, &req)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
finalURL = url
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ func TestClient(t *testing.T) {
|
|||||||
ts := httptest.NewServer(robotsTxtHandler)
|
ts := httptest.NewServer(robotsTxtHandler)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
r, _, err := Get(ts.URL)
|
r, err := Get(ts.URL)
|
||||||
var b []byte
|
var b []byte
|
||||||
if err == nil {
|
if err == nil {
|
||||||
b, err = ioutil.ReadAll(r.Body)
|
b, err = ioutil.ReadAll(r.Body)
|
||||||
@ -96,7 +96,7 @@ func TestRedirects(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
c := &Client{}
|
c := &Client{}
|
||||||
_, _, err := c.Get(ts.URL)
|
_, err := c.Get(ts.URL)
|
||||||
if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
|
if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
|
||||||
t.Errorf("with default client, expected error %q, got %q", e, g)
|
t.Errorf("with default client, expected error %q, got %q", e, g)
|
||||||
}
|
}
|
||||||
@ -107,7 +107,8 @@ func TestRedirects(t *testing.T) {
|
|||||||
lastVia = via
|
lastVia = via
|
||||||
return checkErr
|
return checkErr
|
||||||
}}
|
}}
|
||||||
_, finalUrl, err := c.Get(ts.URL)
|
res, err := c.Get(ts.URL)
|
||||||
|
finalUrl := res.Request.URL.String()
|
||||||
if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
|
if e, g := "<nil>", fmt.Sprintf("%v", err); e != g {
|
||||||
t.Errorf("with custom client, expected error %q, got %q", e, g)
|
t.Errorf("with custom client, expected error %q, got %q", e, g)
|
||||||
}
|
}
|
||||||
@ -119,7 +120,8 @@ func TestRedirects(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkErr = os.NewError("no redirects allowed")
|
checkErr = os.NewError("no redirects allowed")
|
||||||
_, finalUrl, err = c.Get(ts.URL)
|
res, err = c.Get(ts.URL)
|
||||||
|
finalUrl = res.Request.URL.String()
|
||||||
if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
|
if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
|
||||||
t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
|
t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ func TestServeFileContentType(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
get := func(want string) {
|
get := func(want string) {
|
||||||
resp, _, err := Get(ts.URL)
|
resp, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,7 @@ func (cc *ClientConn) Read(req *Request) (*Response, os.Error) {
|
|||||||
|
|
||||||
// readUsing is the implementation of Read with a replaceable
|
// readUsing is the implementation of Read with a replaceable
|
||||||
// ReadResponse-like function, used by the Transport.
|
// ReadResponse-like function, used by the Transport.
|
||||||
func (cc *ClientConn) readUsing(req *Request, readRes func(buf *bufio.Reader, method string) (*Response, os.Error)) (resp *Response, err os.Error) {
|
func (cc *ClientConn) readUsing(req *Request, readRes func(*bufio.Reader, *Request) (*Response, os.Error)) (resp *Response, err os.Error) {
|
||||||
// Retrieve the pipeline ID of this request/response pair
|
// Retrieve the pipeline ID of this request/response pair
|
||||||
cc.lk.Lock()
|
cc.lk.Lock()
|
||||||
id, ok := cc.pipereq[req]
|
id, ok := cc.pipereq[req]
|
||||||
@ -386,7 +386,7 @@ func (cc *ClientConn) readUsing(req *Request, readRes func(buf *bufio.Reader, me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err = readRes(r, req.Method)
|
resp, err = readRes(r, req)
|
||||||
cc.lk.Lock()
|
cc.lk.Lock()
|
||||||
defer cc.lk.Unlock()
|
defer cc.lk.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -162,11 +162,12 @@ func TestRedirect(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
var end = regexp.MustCompile("/foo/$")
|
var end = regexp.MustCompile("/foo/$")
|
||||||
r, url, err := Get(ts.URL)
|
r, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
|
url := r.Request.URL.String()
|
||||||
if r.StatusCode != 200 || !end.MatchString(url) {
|
if r.StatusCode != 200 || !end.MatchString(url) {
|
||||||
t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
|
t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,6 @@ type Response struct {
|
|||||||
ProtoMajor int // e.g. 1
|
ProtoMajor int // e.g. 1
|
||||||
ProtoMinor int // e.g. 0
|
ProtoMinor int // e.g. 0
|
||||||
|
|
||||||
// RequestMethod records the method used in the HTTP request.
|
|
||||||
// Header fields such as Content-Length have method-specific meaning.
|
|
||||||
RequestMethod string // e.g. "HEAD", "CONNECT", "GET", etc.
|
|
||||||
|
|
||||||
// Header maps header keys to values. If the response had multiple
|
// Header maps header keys to values. If the response had multiple
|
||||||
// headers with the same key, they will be concatenated, with comma
|
// headers with the same key, they will be concatenated, with comma
|
||||||
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
|
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
|
||||||
@ -68,19 +64,26 @@ type Response struct {
|
|||||||
// Trailer maps trailer keys to values, in the same
|
// Trailer maps trailer keys to values, in the same
|
||||||
// format as the header.
|
// format as the header.
|
||||||
Trailer Header
|
Trailer Header
|
||||||
|
|
||||||
|
// The Request that was sent to obtain this Response.
|
||||||
|
// Request's Body is nil (having already been consumed).
|
||||||
|
// This is only populated for Client requests.
|
||||||
|
Request *Request
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadResponse reads and returns an HTTP response from r. The RequestMethod
|
// ReadResponse reads and returns an HTTP response from r. The
|
||||||
// parameter specifies the method used in the corresponding request (e.g.,
|
// req parameter specifies the Request that corresponds to
|
||||||
// "GET", "HEAD"). Clients must call resp.Body.Close when finished reading
|
// this Response. Clients must call resp.Body.Close when finished
|
||||||
// resp.Body. After that call, clients can inspect resp.Trailer to find
|
// reading resp.Body. After that call, clients can inspect
|
||||||
// key/value pairs included in the response trailer.
|
// resp.Trailer to find key/value pairs included in the response
|
||||||
func ReadResponse(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
|
// trailer.
|
||||||
|
func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err os.Error) {
|
||||||
|
|
||||||
tp := textproto.NewReader(r)
|
tp := textproto.NewReader(r)
|
||||||
resp = new(Response)
|
resp = new(Response)
|
||||||
|
|
||||||
resp.RequestMethod = strings.ToUpper(requestMethod)
|
resp.Request = req
|
||||||
|
resp.Request.Method = strings.ToUpper(resp.Request.Method)
|
||||||
|
|
||||||
// Parse the first line of the response.
|
// Parse the first line of the response.
|
||||||
line, err := tp.ReadLine()
|
line, err := tp.ReadLine()
|
||||||
@ -164,7 +167,9 @@ func (r *Response) ProtoAtLeast(major, minor int) bool {
|
|||||||
func (resp *Response) Write(w io.Writer) os.Error {
|
func (resp *Response) Write(w io.Writer) os.Error {
|
||||||
|
|
||||||
// RequestMethod should be upper-case
|
// RequestMethod should be upper-case
|
||||||
resp.RequestMethod = strings.ToUpper(resp.RequestMethod)
|
if resp.Request != nil {
|
||||||
|
resp.Request.Method = strings.ToUpper(resp.Request.Method)
|
||||||
|
}
|
||||||
|
|
||||||
// Status line
|
// Status line
|
||||||
text := resp.Status
|
text := resp.Status
|
||||||
|
@ -23,6 +23,10 @@ type respTest struct {
|
|||||||
Body string
|
Body string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dummyReq(method string) *Request {
|
||||||
|
return &Request{Method: method}
|
||||||
|
}
|
||||||
|
|
||||||
var respTests = []respTest{
|
var respTests = []respTest{
|
||||||
// Unchunked response without Content-Length.
|
// Unchunked response without Content-Length.
|
||||||
{
|
{
|
||||||
@ -32,12 +36,12 @@ var respTests = []respTest{
|
|||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"Connection": {"close"}, // TODO(rsc): Delete?
|
"Connection": {"close"}, // TODO(rsc): Delete?
|
||||||
},
|
},
|
||||||
@ -61,7 +65,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.1",
|
Proto: "HTTP/1.1",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: -1,
|
ContentLength: -1,
|
||||||
},
|
},
|
||||||
@ -81,7 +85,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.1",
|
Proto: "HTTP/1.1",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Close: false,
|
Close: false,
|
||||||
ContentLength: 0,
|
ContentLength: 0,
|
||||||
},
|
},
|
||||||
@ -98,12 +102,12 @@ var respTests = []respTest{
|
|||||||
"Body here\n",
|
"Body here\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"Connection": {"close"}, // TODO(rsc): Delete?
|
"Connection": {"close"}, // TODO(rsc): Delete?
|
||||||
"Content-Length": {"10"}, // TODO(rsc): Delete?
|
"Content-Length": {"10"}, // TODO(rsc): Delete?
|
||||||
@ -133,7 +137,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: -1,
|
ContentLength: -1,
|
||||||
@ -160,7 +164,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: -1, // TODO(rsc): Fix?
|
ContentLength: -1, // TODO(rsc): Fix?
|
||||||
@ -183,7 +187,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "HEAD",
|
Request: dummyReq("HEAD"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: 0,
|
ContentLength: 0,
|
||||||
@ -199,12 +203,12 @@ var respTests = []respTest{
|
|||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
Response{
|
Response{
|
||||||
Status: "200 OK",
|
Status: "200 OK",
|
||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
Proto: "HTTP/1.1",
|
Proto: "HTTP/1.1",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"Content-Length": {"0"},
|
"Content-Length": {"0"},
|
||||||
},
|
},
|
||||||
@ -225,7 +229,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: -1,
|
ContentLength: -1,
|
||||||
@ -244,7 +248,7 @@ var respTests = []respTest{
|
|||||||
Proto: "HTTP/1.0",
|
Proto: "HTTP/1.0",
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Close: true,
|
Close: true,
|
||||||
ContentLength: -1,
|
ContentLength: -1,
|
||||||
@ -259,7 +263,7 @@ func TestReadResponse(t *testing.T) {
|
|||||||
tt := &respTests[i]
|
tt := &respTests[i]
|
||||||
var braw bytes.Buffer
|
var braw bytes.Buffer
|
||||||
braw.WriteString(tt.Raw)
|
braw.WriteString(tt.Raw)
|
||||||
resp, err := ReadResponse(bufio.NewReader(&braw), tt.Resp.RequestMethod)
|
resp, err := ReadResponse(bufio.NewReader(&braw), tt.Resp.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("#%d: %s", i, err)
|
t.Errorf("#%d: %s", i, err)
|
||||||
continue
|
continue
|
||||||
@ -340,7 +344,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) {
|
|||||||
buf.WriteString("Next Request Here")
|
buf.WriteString("Next Request Here")
|
||||||
|
|
||||||
bufr := bufio.NewReader(&buf)
|
bufr := bufio.NewReader(&buf)
|
||||||
resp, err := ReadResponse(bufr, "GET")
|
resp, err := ReadResponse(bufr, dummyReq("GET"))
|
||||||
checkErr(err, "ReadResponse")
|
checkErr(err, "ReadResponse")
|
||||||
expectedLength := int64(-1)
|
expectedLength := int64(-1)
|
||||||
if !test.chunked {
|
if !test.chunked {
|
||||||
|
@ -22,7 +22,7 @@ var respWriteTests = []respWriteTest{
|
|||||||
StatusCode: 503,
|
StatusCode: 503,
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
||||||
ContentLength: 6,
|
ContentLength: 6,
|
||||||
@ -38,7 +38,7 @@ var respWriteTests = []respWriteTest{
|
|||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 0,
|
ProtoMinor: 0,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
||||||
ContentLength: -1,
|
ContentLength: -1,
|
||||||
@ -53,7 +53,7 @@ var respWriteTests = []respWriteTest{
|
|||||||
StatusCode: 200,
|
StatusCode: 200,
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{},
|
Header: Header{},
|
||||||
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
Body: ioutil.NopCloser(bytes.NewBufferString("abcdef")),
|
||||||
ContentLength: 6,
|
ContentLength: 6,
|
||||||
@ -71,10 +71,10 @@ var respWriteTests = []respWriteTest{
|
|||||||
// Also tests removal of leading and trailing whitespace.
|
// Also tests removal of leading and trailing whitespace.
|
||||||
{
|
{
|
||||||
Response{
|
Response{
|
||||||
StatusCode: 204,
|
StatusCode: 204,
|
||||||
ProtoMajor: 1,
|
ProtoMajor: 1,
|
||||||
ProtoMinor: 1,
|
ProtoMinor: 1,
|
||||||
RequestMethod: "GET",
|
Request: dummyReq("GET"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"Foo": []string{" Bar\nBaz "},
|
"Foo": []string{" Bar\nBaz "},
|
||||||
},
|
},
|
||||||
|
@ -33,7 +33,7 @@ func TestReverseProxy(t *testing.T) {
|
|||||||
frontend := httptest.NewServer(proxyHandler)
|
frontend := httptest.NewServer(proxyHandler)
|
||||||
defer frontend.Close()
|
defer frontend.Close()
|
||||||
|
|
||||||
res, _, err := Get(frontend.URL)
|
res, err := Get(frontend.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Get: %v", err)
|
t.Fatalf("Get: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ func TestServerTimeouts(t *testing.T) {
|
|||||||
// Hit the HTTP server successfully.
|
// Hit the HTTP server successfully.
|
||||||
tr := &Transport{DisableKeepAlives: true} // they interfere with this test
|
tr := &Transport{DisableKeepAlives: true} // they interfere with this test
|
||||||
c := &Client{Transport: tr}
|
c := &Client{Transport: tr}
|
||||||
r, _, err := c.Get(url)
|
r, err := c.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("http Get #1: %v", err)
|
t.Fatalf("http Get #1: %v", err)
|
||||||
}
|
}
|
||||||
@ -282,7 +282,7 @@ func TestServerTimeouts(t *testing.T) {
|
|||||||
// Hit the HTTP server successfully again, verifying that the
|
// Hit the HTTP server successfully again, verifying that the
|
||||||
// previous slow connection didn't run our handler. (that we
|
// previous slow connection didn't run our handler. (that we
|
||||||
// get "req=2", not "req=3")
|
// get "req=2", not "req=3")
|
||||||
r, _, err = Get(url)
|
r, err = Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("http Get #2: %v", err)
|
t.Fatalf("http Get #2: %v", err)
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ func TestIdentityResponse(t *testing.T) {
|
|||||||
// responses.
|
// responses.
|
||||||
for _, te := range []string{"", "identity"} {
|
for _, te := range []string{"", "identity"} {
|
||||||
url := ts.URL + "/?te=" + te
|
url := ts.URL + "/?te=" + te
|
||||||
res, _, err := Get(url)
|
res, err := Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error with Get of %s: %v", url, err)
|
t.Fatalf("error with Get of %s: %v", url, err)
|
||||||
}
|
}
|
||||||
@ -342,7 +342,7 @@ func TestIdentityResponse(t *testing.T) {
|
|||||||
|
|
||||||
// Verify that ErrContentLength is returned
|
// Verify that ErrContentLength is returned
|
||||||
url := ts.URL + "/?overwrite=1"
|
url := ts.URL + "/?overwrite=1"
|
||||||
_, _, err := Get(url)
|
_, err := Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error with Get of %s: %v", url, err)
|
t.Fatalf("error with Get of %s: %v", url, err)
|
||||||
}
|
}
|
||||||
@ -389,7 +389,7 @@ func TestServeHTTP10Close(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := bufio.NewReader(conn)
|
r := bufio.NewReader(conn)
|
||||||
_, err = ReadResponse(r, "GET")
|
_, err = ReadResponse(r, &Request{Method: "GET"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("ReadResponse error:", err)
|
t.Fatal("ReadResponse error:", err)
|
||||||
}
|
}
|
||||||
@ -417,7 +417,7 @@ func TestSetsRemoteAddr(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
res, _, err := Get(ts.URL)
|
res, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Get error: %v", err)
|
t.Fatalf("Get error: %v", err)
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ func TestChunkedResponseHeaders(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
res, _, err := Get(ts.URL)
|
res, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Get error: %v", err)
|
t.Fatalf("Get error: %v", err)
|
||||||
}
|
}
|
||||||
@ -465,7 +465,7 @@ func Test304Responses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
res, _, err := Get(ts.URL)
|
res, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -516,7 +516,7 @@ func TestTLSServer(t *testing.T) {
|
|||||||
if !strings.HasPrefix(ts.URL, "https://") {
|
if !strings.HasPrefix(ts.URL, "https://") {
|
||||||
t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
|
t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
|
||||||
}
|
}
|
||||||
res, _, err := Get(ts.URL)
|
res, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -657,7 +657,7 @@ func TestTimeoutHandler(t *testing.T) {
|
|||||||
|
|
||||||
// Succeed without timing out:
|
// Succeed without timing out:
|
||||||
sendHi <- true
|
sendHi <- true
|
||||||
res, _, err := Get(ts.URL)
|
res, err := Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -674,7 +674,7 @@ func TestTimeoutHandler(t *testing.T) {
|
|||||||
|
|
||||||
// Times out:
|
// Times out:
|
||||||
timeout <- 1
|
timeout <- 1
|
||||||
res, _, err = Get(ts.URL)
|
res, err = Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
|
|||||||
t.TransferEncoding = rr.TransferEncoding
|
t.TransferEncoding = rr.TransferEncoding
|
||||||
t.Trailer = rr.Trailer
|
t.Trailer = rr.Trailer
|
||||||
atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
|
atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
|
||||||
t.ResponseToHEAD = noBodyExpected(rr.RequestMethod)
|
t.ResponseToHEAD = noBodyExpected(rr.Request.Method)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize Body,ContentLength,TransferEncoding
|
// Sanitize Body,ContentLength,TransferEncoding
|
||||||
@ -196,7 +196,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
|
|||||||
case *Response:
|
case *Response:
|
||||||
t.Header = rr.Header
|
t.Header = rr.Header
|
||||||
t.StatusCode = rr.StatusCode
|
t.StatusCode = rr.StatusCode
|
||||||
t.RequestMethod = rr.RequestMethod
|
t.RequestMethod = rr.Request.Method
|
||||||
t.ProtoMajor = rr.ProtoMajor
|
t.ProtoMajor = rr.ProtoMajor
|
||||||
t.ProtoMinor = rr.ProtoMinor
|
t.ProtoMinor = rr.ProtoMinor
|
||||||
t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
|
t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
|
||||||
|
@ -249,18 +249,22 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case cm.targetScheme == "https":
|
case cm.targetScheme == "https":
|
||||||
fmt.Fprintf(conn, "CONNECT %s HTTP/1.1\r\n", cm.targetAddr)
|
connectReq := &Request{
|
||||||
fmt.Fprintf(conn, "Host: %s\r\n", cm.targetAddr)
|
Method: "CONNECT",
|
||||||
if pa != "" {
|
RawURL: cm.targetAddr,
|
||||||
fmt.Fprintf(conn, "Proxy-Authorization: %s\r\n", pa)
|
Host: cm.targetAddr,
|
||||||
|
Header: make(Header),
|
||||||
}
|
}
|
||||||
fmt.Fprintf(conn, "\r\n")
|
if pa != "" {
|
||||||
|
connectReq.Header.Set("Proxy-Authorization", pa)
|
||||||
|
}
|
||||||
|
connectReq.Write(conn)
|
||||||
|
|
||||||
// Read response.
|
// Read response.
|
||||||
// Okay to use and discard buffered reader here, because
|
// Okay to use and discard buffered reader here, because
|
||||||
// TLS server will not speak until spoken to.
|
// TLS server will not speak until spoken to.
|
||||||
br := bufio.NewReader(conn)
|
br := bufio.NewReader(conn)
|
||||||
resp, err := ReadResponse(br, "CONNECT")
|
resp, err := ReadResponse(br, connectReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -447,8 +451,8 @@ func (pc *persistConn) readLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc := <-pc.reqch
|
rc := <-pc.reqch
|
||||||
resp, err := pc.cc.readUsing(rc.req, func(buf *bufio.Reader, reqMethod string) (*Response, os.Error) {
|
resp, err := pc.cc.readUsing(rc.req, func(buf *bufio.Reader, forReq *Request) (*Response, os.Error) {
|
||||||
resp, err := ReadResponse(buf, reqMethod)
|
resp, err := ReadResponse(buf, forReq)
|
||||||
if err != nil || resp.ContentLength == 0 {
|
if err != nil || resp.ContentLength == 0 {
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func TestTransportKeepAlives(t *testing.T) {
|
|||||||
c := &Client{Transport: tr}
|
c := &Client{Transport: tr}
|
||||||
|
|
||||||
fetch := func(n int) string {
|
fetch := func(n int) string {
|
||||||
res, _, err := c.Get(ts.URL)
|
res, err := c.Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
|
t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
|
|||||||
t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
|
t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, _, err := c.Get(ts.URL)
|
resp, err := c.Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
|
|||||||
// Their responses will hang until we we write to resch, though.
|
// Their responses will hang until we we write to resch, though.
|
||||||
donech := make(chan bool)
|
donech := make(chan bool)
|
||||||
doReq := func() {
|
doReq := func() {
|
||||||
resp, _, err := c.Get(ts.URL)
|
resp, err := c.Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for retries >= 0 {
|
for retries >= 0 {
|
||||||
retries--
|
retries--
|
||||||
res, _, err := c.Get(ts.URL)
|
res, err := c.Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
condFatalf("error in req #%d, GET: %v", n, err)
|
condFatalf("error in req #%d, GET: %v", n, err)
|
||||||
continue
|
continue
|
||||||
@ -420,7 +420,7 @@ func TestTransportGzip(t *testing.T) {
|
|||||||
c := &Client{Transport: &Transport{}}
|
c := &Client{Transport: &Transport{}}
|
||||||
|
|
||||||
// First fetch something large, but only read some of it.
|
// First fetch something large, but only read some of it.
|
||||||
res, _, err := c.Get(ts.URL + "?body=large&chunked=" + chunked)
|
res, err := c.Get(ts.URL + "?body=large&chunked=" + chunked)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("large get: %v", err)
|
t.Fatalf("large get: %v", err)
|
||||||
}
|
}
|
||||||
@ -440,7 +440,7 @@ func TestTransportGzip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Then something small.
|
// Then something small.
|
||||||
res, _, err = c.Get(ts.URL + "?chunked=" + chunked)
|
res, err = c.Get(ts.URL + "?chunked=" + chunked)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -490,7 +490,7 @@ func TestTransportGzipRecursive(t *testing.T) {
|
|||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
c := &Client{Transport: &Transport{}}
|
c := &Client{Transport: &Transport{}}
|
||||||
res, _, err := c.Get(ts.URL)
|
res, err := c.Get(ts.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ func DialHTTPPath(network, address, path string) (*Client, os.Error) {
|
|||||||
|
|
||||||
// Require successful HTTP response
|
// Require successful HTTP response
|
||||||
// before switching to RPC protocol.
|
// before switching to RPC protocol.
|
||||||
resp, err := http.ReadResponse(bufio.NewReader(conn), "CONNECT")
|
resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
|
||||||
if err == nil && resp.Status == connected {
|
if err == nil && resp.Status == connected {
|
||||||
return NewClient(conn), nil
|
return NewClient(conn), nil
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 28-29, 32-40. read response from server.
|
// Step 28-29, 32-40. read response from server.
|
||||||
resp, err := http.ReadResponse(br, "GET")
|
resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ func draft75handshake(resourceName, host, origin, location, protocol string, br
|
|||||||
}
|
}
|
||||||
bw.WriteString("\r\n")
|
bw.WriteString("\r\n")
|
||||||
bw.Flush()
|
bw.Flush()
|
||||||
resp, err := http.ReadResponse(br, "GET")
|
resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ func TestHTTP(t *testing.T) {
|
|||||||
|
|
||||||
// If the client did not send a handshake that matches the protocol
|
// If the client did not send a handshake that matches the protocol
|
||||||
// specification, the server should abort the WebSocket connection.
|
// specification, the server should abort the WebSocket connection.
|
||||||
_, _, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
|
_, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Get: unexpected success")
|
t.Error("Get: unexpected success")
|
||||||
return
|
return
|
||||||
@ -169,7 +169,7 @@ func TestHTTP(t *testing.T) {
|
|||||||
func TestHTTPDraft75(t *testing.T) {
|
func TestHTTPDraft75(t *testing.T) {
|
||||||
once.Do(startServer)
|
once.Do(startServer)
|
||||||
|
|
||||||
r, _, err := http.Get(fmt.Sprintf("http://%s/echoDraft75", serverAddr))
|
r, err := http.Get(fmt.Sprintf("http://%s/echoDraft75", serverAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Get: error %#v", err)
|
t.Errorf("Get: error %#v", err)
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user