2f957d23dbe7b27e94d5da191dbd67afcdc69767
[platform/upstream/gcc.git] / libgo / go / net / http / client.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // HTTP client. See RFC 2616.
6 //
7 // This is the high-level Client interface.
8 // The low-level implementation is in transport.go.
9
10 package http
11
12 import (
13         "encoding/base64"
14         "errors"
15         "fmt"
16         "io"
17         "log"
18         "net/url"
19         "strings"
20 )
21
22 // A Client is an HTTP client. Its zero value (DefaultClient) is a usable client
23 // that uses DefaultTransport.
24 //
25 // The Client's Transport typically has internal state (cached
26 // TCP connections), so Clients should be reused instead of created as
27 // needed. Clients are safe for concurrent use by multiple goroutines.
28 type Client struct {
29         // Transport specifies the mechanism by which individual
30         // HTTP requests are made.
31         // If nil, DefaultTransport is used.
32         Transport RoundTripper
33
34         // CheckRedirect specifies the policy for handling redirects.
35         // If CheckRedirect is not nil, the client calls it before
36         // following an HTTP redirect. The arguments req and via are
37         // the upcoming request and the requests made already, oldest
38         // first. If CheckRedirect returns an error, the Client's Get
39         // method returns both the previous Response and
40         // CheckRedirect's error (wrapped in a url.Error) instead of
41         // issuing the Request req.
42         //
43         // If CheckRedirect is nil, the Client uses its default policy,
44         // which is to stop after 10 consecutive requests.
45         CheckRedirect func(req *Request, via []*Request) error
46
47         // Jar specifies the cookie jar.
48         // If Jar is nil, cookies are not sent in requests and ignored
49         // in responses.
50         Jar CookieJar
51 }
52
53 // DefaultClient is the default Client and is used by Get, Head, and Post.
54 var DefaultClient = &Client{}
55
56 // RoundTripper is an interface representing the ability to execute a
57 // single HTTP transaction, obtaining the Response for a given Request.
58 //
59 // A RoundTripper must be safe for concurrent use by multiple
60 // goroutines.
61 type RoundTripper interface {
62         // RoundTrip executes a single HTTP transaction, returning
63         // the Response for the request req.  RoundTrip should not
64         // attempt to interpret the response.  In particular,
65         // RoundTrip must return err == nil if it obtained a response,
66         // regardless of the response's HTTP status code.  A non-nil
67         // err should be reserved for failure to obtain a response.
68         // Similarly, RoundTrip should not attempt to handle
69         // higher-level protocol details such as redirects,
70         // authentication, or cookies.
71         //
72         // RoundTrip should not modify the request, except for
73         // consuming the Body.  The request's URL and Header fields
74         // are guaranteed to be initialized.
75         RoundTrip(*Request) (*Response, error)
76 }
77
78 // Given a string of the form "host", "host:port", or "[ipv6::address]:port",
79 // return true if the string includes a port.
80 func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
81
82 // Used in Send to implement io.ReadCloser by bundling together the
83 // bufio.Reader through which we read the response, and the underlying
84 // network connection.
85 type readClose struct {
86         io.Reader
87         io.Closer
88 }
89
90 func (c *Client) send(req *Request) (*Response, error) {
91         if c.Jar != nil {
92                 for _, cookie := range c.Jar.Cookies(req.URL) {
93                         req.AddCookie(cookie)
94                 }
95         }
96         resp, err := send(req, c.Transport)
97         if err != nil {
98                 return nil, err
99         }
100         if c.Jar != nil {
101                 c.Jar.SetCookies(req.URL, resp.Cookies())
102         }
103         return resp, err
104 }
105
106 // Do sends an HTTP request and returns an HTTP response, following
107 // policy (e.g. redirects, cookies, auth) as configured on the client.
108 //
109 // An error is returned if caused by client policy (such as
110 // CheckRedirect), or if there was an HTTP protocol error.
111 // A non-2xx response doesn't cause an error.
112 //
113 // When err is nil, resp always contains a non-nil resp.Body.
114 //
115 // Callers should close resp.Body when done reading from it. If
116 // resp.Body is not closed, the Client's underlying RoundTripper
117 // (typically Transport) may not be able to re-use a persistent TCP
118 // connection to the server for a subsequent "keep-alive" request.
119 //
120 // Generally Get, Post, or PostForm will be used instead of Do.
121 func (c *Client) Do(req *Request) (resp *Response, err error) {
122         if req.Method == "GET" || req.Method == "HEAD" {
123                 return c.doFollowingRedirects(req)
124         }
125         return c.send(req)
126 }
127
128 // send issues an HTTP request.
129 // Caller should close resp.Body when done reading from it.
130 func send(req *Request, t RoundTripper) (resp *Response, err error) {
131         if t == nil {
132                 t = DefaultTransport
133                 if t == nil {
134                         err = errors.New("http: no Client.Transport or DefaultTransport")
135                         return
136                 }
137         }
138
139         if req.URL == nil {
140                 return nil, errors.New("http: nil Request.URL")
141         }
142
143         if req.RequestURI != "" {
144                 return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
145         }
146
147         // Most the callers of send (Get, Post, et al) don't need
148         // Headers, leaving it uninitialized.  We guarantee to the
149         // Transport that this has been initialized, though.
150         if req.Header == nil {
151                 req.Header = make(Header)
152         }
153
154         if u := req.URL.User; u != nil {
155                 req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
156         }
157         resp, err = t.RoundTrip(req)
158         if err != nil {
159                 if resp != nil {
160                         log.Printf("RoundTripper returned a response & error; ignoring response")
161                 }
162                 return nil, err
163         }
164         return resp, nil
165 }
166
167 // True if the specified HTTP status code is one for which the Get utility should
168 // automatically redirect.
169 func shouldRedirect(statusCode int) bool {
170         switch statusCode {
171         case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
172                 return true
173         }
174         return false
175 }
176
177 // Get issues a GET to the specified URL.  If the response is one of the following
178 // redirect codes, Get follows the redirect, up to a maximum of 10 redirects:
179 //
180 //    301 (Moved Permanently)
181 //    302 (Found)
182 //    303 (See Other)
183 //    307 (Temporary Redirect)
184 //
185 // An error is returned if there were too many redirects or if there
186 // was an HTTP protocol error. A non-2xx response doesn't cause an
187 // error.
188 //
189 // When err is nil, resp always contains a non-nil resp.Body.
190 // Caller should close resp.Body when done reading from it.
191 //
192 // Get is a wrapper around DefaultClient.Get.
193 func Get(url string) (resp *Response, err error) {
194         return DefaultClient.Get(url)
195 }
196
197 // Get issues a GET to the specified URL.  If the response is one of the
198 // following redirect codes, Get follows the redirect after calling the
199 // Client's CheckRedirect function.
200 //
201 //    301 (Moved Permanently)
202 //    302 (Found)
203 //    303 (See Other)
204 //    307 (Temporary Redirect)
205 //
206 // An error is returned if the Client's CheckRedirect function fails
207 // or if there was an HTTP protocol error. A non-2xx response doesn't
208 // cause an error.
209 //
210 // When err is nil, resp always contains a non-nil resp.Body.
211 // Caller should close resp.Body when done reading from it.
212 func (c *Client) Get(url string) (resp *Response, err error) {
213         req, err := NewRequest("GET", url, nil)
214         if err != nil {
215                 return nil, err
216         }
217         return c.doFollowingRedirects(req)
218 }
219
220 func (c *Client) doFollowingRedirects(ireq *Request) (resp *Response, err error) {
221         // TODO: if/when we add cookie support, the redirected request shouldn't
222         // necessarily supply the same cookies as the original.
223         var base *url.URL
224         redirectChecker := c.CheckRedirect
225         if redirectChecker == nil {
226                 redirectChecker = defaultCheckRedirect
227         }
228         var via []*Request
229
230         if ireq.URL == nil {
231                 return nil, errors.New("http: nil Request.URL")
232         }
233
234         req := ireq
235         urlStr := "" // next relative or absolute URL to fetch (after first request)
236         redirectFailed := false
237         for redirect := 0; ; redirect++ {
238                 if redirect != 0 {
239                         req = new(Request)
240                         req.Method = ireq.Method
241                         req.Header = make(Header)
242                         req.URL, err = base.Parse(urlStr)
243                         if err != nil {
244                                 break
245                         }
246                         if len(via) > 0 {
247                                 // Add the Referer header.
248                                 lastReq := via[len(via)-1]
249                                 if lastReq.URL.Scheme != "https" {
250                                         req.Header.Set("Referer", lastReq.URL.String())
251                                 }
252
253                                 err = redirectChecker(req, via)
254                                 if err != nil {
255                                         redirectFailed = true
256                                         break
257                                 }
258                         }
259                 }
260
261                 urlStr = req.URL.String()
262                 if resp, err = c.send(req); err != nil {
263                         break
264                 }
265
266                 if shouldRedirect(resp.StatusCode) {
267                         resp.Body.Close()
268                         if urlStr = resp.Header.Get("Location"); urlStr == "" {
269                                 err = errors.New(fmt.Sprintf("%d response missing Location header", resp.StatusCode))
270                                 break
271                         }
272                         base = req.URL
273                         via = append(via, req)
274                         continue
275                 }
276                 return
277         }
278
279         method := ireq.Method
280         urlErr := &url.Error{
281                 Op:  method[0:1] + strings.ToLower(method[1:]),
282                 URL: urlStr,
283                 Err: err,
284         }
285
286         if redirectFailed {
287                 // Special case for Go 1 compatibility: return both the response
288                 // and an error if the CheckRedirect function failed.
289                 // See http://golang.org/issue/3795
290                 return resp, urlErr
291         }
292
293         if resp != nil {
294                 resp.Body.Close()
295         }
296         return nil, urlErr
297 }
298
299 func defaultCheckRedirect(req *Request, via []*Request) error {
300         if len(via) >= 10 {
301                 return errors.New("stopped after 10 redirects")
302         }
303         return nil
304 }
305
306 // Post issues a POST to the specified URL.
307 //
308 // Caller should close resp.Body when done reading from it.
309 //
310 // Post is a wrapper around DefaultClient.Post
311 func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
312         return DefaultClient.Post(url, bodyType, body)
313 }
314
315 // Post issues a POST to the specified URL.
316 //
317 // Caller should close resp.Body when done reading from it.
318 func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
319         req, err := NewRequest("POST", url, body)
320         if err != nil {
321                 return nil, err
322         }
323         req.Header.Set("Content-Type", bodyType)
324         return c.send(req)
325 }
326
327 // PostForm issues a POST to the specified URL, with data's keys and
328 // values URL-encoded as the request body.
329 //
330 // When err is nil, resp always contains a non-nil resp.Body.
331 // Caller should close resp.Body when done reading from it.
332 //
333 // PostForm is a wrapper around DefaultClient.PostForm
334 func PostForm(url string, data url.Values) (resp *Response, err error) {
335         return DefaultClient.PostForm(url, data)
336 }
337
338 // PostForm issues a POST to the specified URL,
339 // with data's keys and values urlencoded as the request body.
340 //
341 // When err is nil, resp always contains a non-nil resp.Body.
342 // Caller should close resp.Body when done reading from it.
343 func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
344         return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
345 }
346
347 // Head issues a HEAD to the specified URL.  If the response is one of the
348 // following redirect codes, Head follows the redirect after calling the
349 // Client's CheckRedirect function.
350 //
351 //    301 (Moved Permanently)
352 //    302 (Found)
353 //    303 (See Other)
354 //    307 (Temporary Redirect)
355 //
356 // Head is a wrapper around DefaultClient.Head
357 func Head(url string) (resp *Response, err error) {
358         return DefaultClient.Head(url)
359 }
360
361 // Head issues a HEAD to the specified URL.  If the response is one of the
362 // following redirect codes, Head follows the redirect after calling the
363 // Client's CheckRedirect function.
364 //
365 //    301 (Moved Permanently)
366 //    302 (Found)
367 //    303 (See Other)
368 //    307 (Temporary Redirect)
369 func (c *Client) Head(url string) (resp *Response, err error) {
370         req, err := NewRequest("HEAD", url, nil)
371         if err != nil {
372                 return nil, err
373         }
374         return c.doFollowingRedirects(req)
375 }