Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(337)

Delta Between Two Patch Sets: src/pkg/http/client.go

Issue 4239044: code review 4239044: http: expose Client's Transport (Closed)
Left Patch Set: diff -r 9942dde5fdad https://go.googlecode.com/hg/ Created 14 years ago
Right Patch Set: diff -r c8dd9e29a20c https://go.googlecode.com/hg/ Created 14 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/http/client_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Primitive HTTP client. See RFC 2616. 5 // Primitive HTTP client. See RFC 2616.
6 6
7 package http 7 package http
8 8
9 import ( 9 import (
10 "bytes" 10 "bytes"
11 "encoding/base64" 11 "encoding/base64"
12 "fmt" 12 "fmt"
13 "io" 13 "io"
14 "os" 14 "os"
15 "strconv" 15 "strconv"
16 "strings" 16 "strings"
17 ) 17 )
18 18
19 // A Client is an HTTP client. 19 // A Client is an HTTP client. Its zero value (DefaultClient) is a usable client
20 // It is not yet possible to create custom Clients; use DefaultClient. 20 // that uses DefaultTransport.
21 // Client is not yet very configurable.
21 type Client struct { 22 type Client struct {
22 Transport ClientTransport // if nil, DefaultTransport is used 23 Transport ClientTransport // if nil, DefaultTransport is used
23
24 unused int // prevent instantiation; there will likely be internal state in the future
25 } 24 }
26 25
27 // DefaultClient is the default Client and is used by Get, Head, and Post. 26 // DefaultClient is the default Client and is used by Get, Head, and Post.
28 var DefaultClient = &Client{} 27 var DefaultClient = &Client{}
29
30 // NewClient returns a new Client which you can then initialize as needed.
31 func NewClient() *Client {
32 return &Client{}
33 }
34 28
35 // ClientTransport is an interface representing the ability to execute a 29 // ClientTransport is an interface representing the ability to execute a
36 // single HTTP transaction, obtaining the Response for a given Request. 30 // single HTTP transaction, obtaining the Response for a given Request.
37 type ClientTransport interface { 31 type ClientTransport interface {
38 // Do executes a single HTTP transaction, returning the Response for the 32 // Do executes a single HTTP transaction, returning the Response for the
39 // request req. Do should not attempt to interpret the response. 33 // request req. Do should not attempt to interpret the response.
40 // In particular, Do must return err == nil if it obtained a response, 34 // In particular, Do must return err == nil if it obtained a response,
41 // regardless of the response's HTTP status code. A non-nil err should 35 // regardless of the response's HTTP status code. A non-nil err should
42 // be reserved for failure to obtain a response. Similarly, Do should 36 // be reserved for failure to obtain a response. Similarly, Do should
43 // not attempt to handle higher-level protocol details such as redirects , 37 // not attempt to handle higher-level protocol details such as redirects ,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || a ddr == p[1:])) { 81 if addr == p || (p[0] == '.' && (strings.HasSuffix(addr, p) || a ddr == p[1:])) {
88 return true 82 return true
89 } 83 }
90 } 84 }
91 return false 85 return false
92 } 86 }
93 87
94 // Do sends an HTTP request and returns an HTTP response, following 88 // Do sends an HTTP request and returns an HTTP response, following
95 // policy (e.g. redirects, cookies, auth) as configured on the client. 89 // policy (e.g. redirects, cookies, auth) as configured on the client.
96 // 90 //
97 // Callers should close resp.Body when done reading it. 91 // Callers should close resp.Body when done reading from it.
98 // 92 //
99 // Generally Get, Post, or PostForm will be used instead of Do. 93 // Generally Get, Post, or PostForm will be used instead of Do.
100 func (c *Client) Do(req *Request) (resp *Response, err os.Error) { 94 func (c *Client) Do(req *Request) (resp *Response, err os.Error) {
101 return send(req, c.Transport) 95 return send(req, c.Transport)
102 } 96 }
103 97
104 98
105 // send issues an HTTP request. Caller should close resp.Body when done reading it. 99 // send issues an HTTP request. Caller should close resp.Body when done reading from it.
106 // 100 //
107 // TODO: support persistent connections (multiple requests on a single connectio n). 101 // TODO: support persistent connections (multiple requests on a single connectio n).
108 // send() method is nonpublic because, when we refactor the code for persistent 102 // send() method is nonpublic because, when we refactor the code for persistent
109 // connections, it may no longer make sense to have a method with this signature . 103 // connections, it may no longer make sense to have a method with this signature .
110 func send(req *Request, t ClientTransport) (resp *Response, err os.Error) { 104 func send(req *Request, t ClientTransport) (resp *Response, err os.Error) {
111 if t == nil { 105 if t == nil {
112 t = DefaultTransport 106 t = DefaultTransport
113 if t == nil { 107 if t == nil {
114 err = os.NewError("no http.Client.Transport or http.Defa ultTransport") 108 err = os.NewError("no http.Client.Transport or http.Defa ultTransport")
115 return 109 return
(...skipping 26 matching lines...) Expand all
142 // redirect codes, it follows the redirect, up to a maximum of 10 redirects: 136 // redirect codes, it follows the redirect, up to a maximum of 10 redirects:
143 // 137 //
144 // 301 (Moved Permanently) 138 // 301 (Moved Permanently)
145 // 302 (Found) 139 // 302 (Found)
146 // 303 (See Other) 140 // 303 (See Other)
147 // 307 (Temporary Redirect) 141 // 307 (Temporary Redirect)
148 // 142 //
149 // finalURL is the URL from which the response was fetched -- identical to the 143 // finalURL is the URL from which the response was fetched -- identical to the
150 // input URL unless redirects were followed. 144 // input URL unless redirects were followed.
151 // 145 //
152 // Caller should close r.Body when done reading it. 146 // Caller should close r.Body when done reading from it.
153 // 147 //
154 // Get is a convenience wrapper around DefaultClient.Get. 148 // Get is a convenience wrapper around DefaultClient.Get.
155 func Get(url string) (r *Response, finalURL string, err os.Error) { 149 func Get(url string) (r *Response, finalURL string, err os.Error) {
156 return DefaultClient.Get(url) 150 return DefaultClient.Get(url)
157 } 151 }
158 152
159 // Get issues a GET to the specified URL. If the response is one of the followi ng 153 // Get issues a GET to the specified URL. If the response is one of the followi ng
160 // redirect codes, it follows the redirect, up to a maximum of 10 redirects: 154 // redirect codes, it follows the redirect, up to a maximum of 10 redirects:
161 // 155 //
162 // 301 (Moved Permanently) 156 // 301 (Moved Permanently)
163 // 302 (Found) 157 // 302 (Found)
164 // 303 (See Other) 158 // 303 (See Other)
165 // 307 (Temporary Redirect) 159 // 307 (Temporary Redirect)
166 // 160 //
167 // finalURL is the URL from which the response was fetched -- identical to the 161 // finalURL is the URL from which the response was fetched -- identical to the
168 // input URL unless redirects were followed. 162 // input URL unless redirects were followed.
169 // 163 //
170 // Caller should close r.Body when done reading it. 164 // Caller should close r.Body when done reading from it.
171 func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) { 165 func (c *Client) Get(url string) (r *Response, finalURL string, err os.Error) {
172 // TODO: if/when we add cookie support, the redirected request shouldn't 166 // TODO: if/when we add cookie support, the redirected request shouldn't
173 // necessarily supply the same cookies as the original. 167 // necessarily supply the same cookies as the original.
174 // TODO: set referrer header on redirects. 168 // TODO: set referrer header on redirects.
175 var base *URL 169 var base *URL
176 // TODO: remove this hard-coded 10 and use the Client's policy 170 // TODO: remove this hard-coded 10 and use the Client's policy
177 // (ClientConfig) instead. 171 // (ClientConfig) instead.
178 for redirect := 0; ; redirect++ { 172 for redirect := 0; ; redirect++ {
179 if redirect >= 10 { 173 if redirect >= 10 {
180 err = os.ErrorString("stopped after 10 redirects") 174 err = os.ErrorString("stopped after 10 redirects")
(...skipping 28 matching lines...) Expand all
209 finalURL = url 203 finalURL = url
210 return 204 return
211 } 205 }
212 206
213 err = &URLError{"Get", url, err} 207 err = &URLError{"Get", url, err}
214 return 208 return
215 } 209 }
216 210
217 // Post issues a POST to the specified URL. 211 // Post issues a POST to the specified URL.
218 // 212 //
219 // Caller should close r.Body when done reading it. 213 // Caller should close r.Body when done reading from it.
220 // 214 //
221 // Post is a wrapper around DefaultClient.Post 215 // Post is a wrapper around DefaultClient.Post
222 func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Erro r) { 216 func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Erro r) {
223 return DefaultClient.Post(url, bodyType, body) 217 return DefaultClient.Post(url, bodyType, body)
224 } 218 }
225 219
226 // Post issues a POST to the specified URL. 220 // Post issues a POST to the specified URL.
227 // 221 //
228 // Caller should close r.Body when done reading it. 222 // Caller should close r.Body when done reading from it.
229 func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) { 223 func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err os.Error) {
230 var req Request 224 var req Request
231 req.Method = "POST" 225 req.Method = "POST"
232 req.ProtoMajor = 1 226 req.ProtoMajor = 1
233 req.ProtoMinor = 1 227 req.ProtoMinor = 1
234 req.Close = true 228 req.Close = true
235 req.Body = nopCloser{body} 229 req.Body = nopCloser{body}
236 req.Header = Header{ 230 req.Header = Header{
237 "Content-Type": {bodyType}, 231 "Content-Type": {bodyType},
238 } 232 }
239 req.TransferEncoding = []string{"chunked"} 233 req.TransferEncoding = []string{"chunked"}
240 234
241 req.URL, err = ParseURL(url) 235 req.URL, err = ParseURL(url)
242 if err != nil { 236 if err != nil {
243 return nil, err 237 return nil, err
244 } 238 }
245 239
246 return send(&req, c.Transport) 240 return send(&req, c.Transport)
247 } 241 }
248 242
249 // PostForm issues a POST to the specified URL,· 243 // PostForm issues a POST to the specified URL,·
250 // with data's keys and values urlencoded as the request body. 244 // with data's keys and values urlencoded as the request body.
251 // 245 //
252 // Caller should close r.Body when done reading it. 246 // Caller should close r.Body when done reading from it.
253 // 247 //
254 // PostForm is a wrapper around DefaultClient.PostForm 248 // PostForm is a wrapper around DefaultClient.PostForm
255 func PostForm(url string, data map[string]string) (r *Response, err os.Error) { 249 func PostForm(url string, data map[string]string) (r *Response, err os.Error) {
256 return DefaultClient.PostForm(url, data) 250 return DefaultClient.PostForm(url, data)
257 } 251 }
258 252
259 // PostForm issues a POST to the specified URL,· 253 // PostForm issues a POST to the specified URL,·
260 // with data's keys and values urlencoded as the request body. 254 // with data's keys and values urlencoded as the request body.
261 // 255 //
262 // Caller should close r.Body when done reading it. 256 // Caller should close r.Body when done reading from it.
263 func (c *Client) PostForm(url string, data map[string]string) (r *Response, err os.Error) { 257 func (c *Client) PostForm(url string, data map[string]string) (r *Response, err os.Error) {
264 var req Request 258 var req Request
265 req.Method = "POST" 259 req.Method = "POST"
266 req.ProtoMajor = 1 260 req.ProtoMajor = 1
267 req.ProtoMinor = 1 261 req.ProtoMinor = 1
268 req.Close = true 262 req.Close = true
269 body := urlencode(data) 263 body := urlencode(data)
270 req.Body = nopCloser{body} 264 req.Body = nopCloser{body}
271 req.Header = Header{ 265 req.Header = Header{
272 "Content-Type": {"application/x-www-form-urlencoded"}, 266 "Content-Type": {"application/x-www-form-urlencoded"},
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 return 300 return
307 } 301 }
308 return send(&req, c.Transport) 302 return send(&req, c.Transport)
309 } 303 }
310 304
311 type nopCloser struct { 305 type nopCloser struct {
312 io.Reader 306 io.Reader
313 } 307 }
314 308
315 func (nopCloser) Close() os.Error { return nil } 309 func (nopCloser) Close() os.Error { return nil }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b