aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/http/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/client.go')
-rw-r--r--libgo/go/net/http/client.go73
1 files changed, 55 insertions, 18 deletions
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 6f6024e..8f69a29 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// HTTP client. See RFC 2616.
+// HTTP client. See RFC 7230 through 7235.
//
// This is the high-level Client interface.
// The low-level implementation is in transport.go.
@@ -95,14 +95,12 @@ type Client struct {
// A Timeout of zero means no timeout.
//
// The Client cancels requests to the underlying Transport
- // using the Request.Cancel mechanism. Requests passed
- // to Client.Do may still set Request.Cancel; both will
- // cancel the request.
+ // as if the Request's Context ended.
//
// For compatibility, the Client will also use the deprecated
// CancelRequest method on Transport if found. New
- // RoundTripper implementations should use Request.Cancel
- // instead of implementing CancelRequest.
+ // RoundTripper implementations should use the Request's Context
+ // for cancelation instead of implementing CancelRequest.
Timeout time.Duration
}
@@ -129,8 +127,8 @@ type RoundTripper interface {
// RoundTrip should not modify the request, except for
// consuming and closing the Request's Body. RoundTrip may
// read fields of the request in a separate goroutine. Callers
- // should not mutate the request until the Response's Body has
- // been closed.
+ // should not mutate or reuse the request until the Response's
+ // Body has been closed.
//
// RoundTrip must always close the body, including on errors,
// but depending on the implementation may do so in a separate
@@ -335,7 +333,7 @@ func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTi
return stopTimer, timedOut.isSet
}
-// See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
+// See 2 (end of page 4) https://www.ietf.org/rfc/rfc2617.txt
// "To receive authorization, the client sends the userid and password,
// separated by a single colon (":") character, within a base64
// encoded string in the credentials."
@@ -357,7 +355,9 @@ func basicAuth(username, password string) string {
//
// An error is returned if there were too many redirects or if there
// was an HTTP protocol error. A non-2xx response doesn't cause an
-// error.
+// error. Any returned error will be of type *url.Error. The url.Error
+// value's Timeout method will report true if request timed out or was
+// canceled.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
@@ -382,7 +382,9 @@ func Get(url string) (resp *Response, err error) {
//
// An error is returned if the Client's CheckRedirect function fails
// or if there was an HTTP protocol error. A non-2xx response doesn't
-// cause an error.
+// cause an error. Any returned error will be of type *url.Error. The
+// url.Error value's Timeout method will report true if request timed
+// out or was canceled.
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
@@ -457,6 +459,15 @@ func redirectBehavior(reqMethod string, resp *Response, ireq *Request) (redirect
return redirectMethod, shouldRedirect, includeBody
}
+// urlErrorOp returns the (*url.Error).Op value to use for the
+// provided (*Request).Method value.
+func urlErrorOp(method string) string {
+ if method == "" {
+ return "Get"
+ }
+ return method[:1] + strings.ToLower(method[1:])
+}
+
// Do sends an HTTP request and returns an HTTP response, following
// policy (such as redirects, cookies, auth) as configured on the
// client.
@@ -490,10 +501,26 @@ func redirectBehavior(reqMethod string, resp *Response, ireq *Request) (redirect
// provided that the Request.GetBody function is defined.
// The NewRequest function automatically sets GetBody for common
// standard library body types.
+//
+// Any returned error will be of type *url.Error. The url.Error
+// value's Timeout method will report true if request timed out or was
+// canceled.
func (c *Client) Do(req *Request) (*Response, error) {
+ return c.do(req)
+}
+
+var testHookClientDoResult func(retres *Response, reterr error)
+
+func (c *Client) do(req *Request) (retres *Response, reterr error) {
+ if testHookClientDoResult != nil {
+ defer func() { testHookClientDoResult(retres, reterr) }()
+ }
if req.URL == nil {
req.closeBody()
- return nil, errors.New("http: nil Request.URL")
+ return nil, &url.Error{
+ Op: urlErrorOp(req.Method),
+ Err: errors.New("http: nil Request.URL"),
+ }
}
var (
@@ -512,15 +539,14 @@ func (c *Client) Do(req *Request) (*Response, error) {
if !reqBodyClosed {
req.closeBody()
}
- method := valueOrDefault(reqs[0].Method, "GET")
var urlStr string
if resp != nil && resp.Request != nil {
- urlStr = resp.Request.URL.String()
+ urlStr = stripPassword(resp.Request.URL)
} else {
- urlStr = req.URL.String()
+ urlStr = stripPassword(req.URL)
}
return &url.Error{
- Op: method[:1] + strings.ToLower(method[1:]),
+ Op: urlErrorOp(reqs[0].Method),
URL: urlStr,
Err: err,
}
@@ -617,6 +643,7 @@ func (c *Client) Do(req *Request) (*Response, error) {
reqBodyClosed = true
if !deadline.IsZero() && didTimeout() {
err = &httpError{
+ // TODO: early in cycle: s/Client.Timeout exceeded/timeout or context cancelation/
err: err.Error() + " (Client.Timeout exceeded while awaiting headers)",
timeout: true,
}
@@ -718,7 +745,7 @@ func defaultCheckRedirect(req *Request, via []*Request) error {
//
// See the Client.Do method documentation for details on how redirects
// are handled.
-func Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
+func Post(url, contentType string, body io.Reader) (resp *Response, err error) {
return DefaultClient.Post(url, contentType, body)
}
@@ -733,7 +760,7 @@ func Post(url string, contentType string, body io.Reader) (resp *Response, err e
//
// See the Client.Do method documentation for details on how redirects
// are handled.
-func (c *Client) Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
+func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) {
req, err := NewRequest("POST", url, body)
if err != nil {
return nil, err
@@ -827,6 +854,7 @@ func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
}
if b.reqDidTimeout() {
err = &httpError{
+ // TODO: early in cycle: s/Client.Timeout exceeded/timeout or context cancelation/
err: err.Error() + " (Client.Timeout exceeded while reading body)",
timeout: true,
}
@@ -880,3 +908,12 @@ func isDomainOrSubdomain(sub, parent string) bool {
}
return sub[len(sub)-len(parent)-1] == '.'
}
+
+func stripPassword(u *url.URL) string {
+ pass, passSet := u.User.Password()
+ if passSet {
+ return strings.Replace(u.String(), pass+"@", "***@", 1)
+ }
+
+ return u.String()
+}