##// END OF EJS Templates
httpclient: import 4bb625347d4a to provide SSL wrapper injection...
Augie Fackler -
r19807:c48df403 default
parent child Browse files
Show More
@@ -1,717 +1,728
1 1 # Copyright 2010, Google Inc.
2 2 # All rights reserved.
3 3 #
4 4 # Redistribution and use in source and binary forms, with or without
5 5 # modification, are permitted provided that the following conditions are
6 6 # met:
7 7 #
8 8 # * Redistributions of source code must retain the above copyright
9 9 # notice, this list of conditions and the following disclaimer.
10 10 # * Redistributions in binary form must reproduce the above
11 11 # copyright notice, this list of conditions and the following disclaimer
12 12 # in the documentation and/or other materials provided with the
13 13 # distribution.
14 14 # * Neither the name of Google Inc. nor the names of its
15 15 # contributors may be used to endorse or promote products derived from
16 16 # this software without specific prior written permission.
17 17
18 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29 """Improved HTTP/1.1 client library
30 30
31 31 This library contains an HTTPConnection which is similar to the one in
32 32 httplib, but has several additional features:
33 33
34 34 * supports keepalives natively
35 35 * uses select() to block for incoming data
36 36 * notices when the server responds early to a request
37 37 * implements ssl inline instead of in a different class
38 38 """
39 39
40 40 # Many functions in this file have too many arguments.
41 41 # pylint: disable=R0913
42 42
43 43 import cStringIO
44 44 import errno
45 45 import httplib
46 46 import logging
47 47 import rfc822
48 48 import select
49 49 import socket
50 50
51 51 import _readers
52 52 import socketutil
53 53
54 54 logger = logging.getLogger(__name__)
55 55
56 56 __all__ = ['HTTPConnection', 'HTTPResponse']
57 57
58 58 HTTP_VER_1_0 = 'HTTP/1.0'
59 59 HTTP_VER_1_1 = 'HTTP/1.1'
60 60
61 61 OUTGOING_BUFFER_SIZE = 1 << 15
62 62 INCOMING_BUFFER_SIZE = 1 << 20
63 63
64 64 HDR_ACCEPT_ENCODING = 'accept-encoding'
65 65 HDR_CONNECTION_CTRL = 'connection'
66 66 HDR_CONTENT_LENGTH = 'content-length'
67 67 HDR_XFER_ENCODING = 'transfer-encoding'
68 68
69 69 XFER_ENCODING_CHUNKED = 'chunked'
70 70
71 71 CONNECTION_CLOSE = 'close'
72 72
73 73 EOL = '\r\n'
74 74 _END_HEADERS = EOL * 2
75 75
76 76 # Based on some searching around, 1 second seems like a reasonable
77 77 # default here.
78 78 TIMEOUT_ASSUME_CONTINUE = 1
79 79 TIMEOUT_DEFAULT = None
80 80
81 81
82 82 class HTTPResponse(object):
83 83 """Response from an HTTP server.
84 84
85 85 The response will continue to load as available. If you need the
86 86 complete response before continuing, check the .complete() method.
87 87 """
88 88 def __init__(self, sock, timeout, method):
89 89 self.sock = sock
90 90 self.method = method
91 91 self.raw_response = ''
92 92 self._headers_len = 0
93 93 self.headers = None
94 94 self.will_close = False
95 95 self.status_line = ''
96 96 self.status = None
97 97 self.continued = False
98 98 self.http_version = None
99 99 self.reason = None
100 100 self._reader = None
101 101
102 102 self._read_location = 0
103 103 self._eol = EOL
104 104
105 105 self._timeout = timeout
106 106
107 107 @property
108 108 def _end_headers(self):
109 109 return self._eol * 2
110 110
111 111 def complete(self):
112 112 """Returns true if this response is completely loaded.
113 113
114 114 Note that if this is a connection where complete means the
115 115 socket is closed, this will nearly always return False, even
116 116 in cases where all the data has actually been loaded.
117 117 """
118 118 if self._reader:
119 119 return self._reader.done()
120 120
121 121 def _close(self):
122 122 if self._reader is not None:
123 123 # We're a friend of the reader class here.
124 124 # pylint: disable=W0212
125 125 self._reader._close()
126 126
127 127 def readline(self):
128 128 """Read a single line from the response body.
129 129
130 130 This may block until either a line ending is found or the
131 131 response is complete.
132 132 """
133 133 blocks = []
134 134 while True:
135 135 self._reader.readto('\n', blocks)
136 136
137 137 if blocks and blocks[-1][-1] == '\n' or self.complete():
138 138 break
139 139
140 140 self._select()
141 141
142 142 return ''.join(blocks)
143 143
144 144 def read(self, length=None):
145 145 """Read data from the response body."""
146 146 # if length is None, unbounded read
147 147 while (not self.complete() # never select on a finished read
148 148 and (not length # unbounded, so we wait for complete()
149 149 or length > self._reader.available_data)):
150 150 self._select()
151 151 if not length:
152 152 length = self._reader.available_data
153 153 r = self._reader.read(length)
154 154 if self.complete() and self.will_close:
155 155 self.sock.close()
156 156 return r
157 157
158 158 def _select(self):
159 159 r, unused_write, unused_err = select.select(
160 160 [self.sock], [], [], self._timeout)
161 161 if not r:
162 162 # socket was not readable. If the response is not
163 163 # complete, raise a timeout.
164 164 if not self.complete():
165 165 logger.info('timed out with timeout of %s', self._timeout)
166 166 raise HTTPTimeoutException('timeout reading data')
167 167 try:
168 168 data = self.sock.recv(INCOMING_BUFFER_SIZE)
169 169 except socket.sslerror, e:
170 170 if e.args[0] != socket.SSL_ERROR_WANT_READ:
171 171 raise
172 172 logger.debug('SSL_ERROR_WANT_READ in _select, should retry later')
173 173 return True
174 174 logger.debug('response read %d data during _select', len(data))
175 175 # If the socket was readable and no data was read, that means
176 176 # the socket was closed. Inform the reader (if any) so it can
177 177 # raise an exception if this is an invalid situation.
178 178 if not data:
179 179 if self._reader:
180 180 # We're a friend of the reader class here.
181 181 # pylint: disable=W0212
182 182 self._reader._close()
183 183 return False
184 184 else:
185 185 self._load_response(data)
186 186 return True
187 187
188 188 # This method gets replaced by _load later, which confuses pylint.
189 189 def _load_response(self, data): # pylint: disable=E0202
190 190 # Being here implies we're not at the end of the headers yet,
191 191 # since at the end of this method if headers were completely
192 192 # loaded we replace this method with the load() method of the
193 193 # reader we created.
194 194 self.raw_response += data
195 195 # This is a bogus server with bad line endings
196 196 if self._eol not in self.raw_response:
197 197 for bad_eol in ('\n', '\r'):
198 198 if (bad_eol in self.raw_response
199 199 # verify that bad_eol is not the end of the incoming data
200 200 # as this could be a response line that just got
201 201 # split between \r and \n.
202 202 and (self.raw_response.index(bad_eol) <
203 203 (len(self.raw_response) - 1))):
204 204 logger.info('bogus line endings detected, '
205 205 'using %r for EOL', bad_eol)
206 206 self._eol = bad_eol
207 207 break
208 208 # exit early if not at end of headers
209 209 if self._end_headers not in self.raw_response or self.headers:
210 210 return
211 211
212 212 # handle 100-continue response
213 213 hdrs, body = self.raw_response.split(self._end_headers, 1)
214 214 unused_http_ver, status = hdrs.split(' ', 1)
215 215 if status.startswith('100'):
216 216 self.raw_response = body
217 217 self.continued = True
218 218 logger.debug('continue seen, setting body to %r', body)
219 219 return
220 220
221 221 # arriving here means we should parse response headers
222 222 # as all headers have arrived completely
223 223 hdrs, body = self.raw_response.split(self._end_headers, 1)
224 224 del self.raw_response
225 225 if self._eol in hdrs:
226 226 self.status_line, hdrs = hdrs.split(self._eol, 1)
227 227 else:
228 228 self.status_line = hdrs
229 229 hdrs = ''
230 230 # TODO HTTP < 1.0 support
231 231 (self.http_version, self.status,
232 232 self.reason) = self.status_line.split(' ', 2)
233 233 self.status = int(self.status)
234 234 if self._eol != EOL:
235 235 hdrs = hdrs.replace(self._eol, '\r\n')
236 236 headers = rfc822.Message(cStringIO.StringIO(hdrs))
237 237 content_len = None
238 238 if HDR_CONTENT_LENGTH in headers:
239 239 content_len = int(headers[HDR_CONTENT_LENGTH])
240 240 if self.http_version == HTTP_VER_1_0:
241 241 self.will_close = True
242 242 elif HDR_CONNECTION_CTRL in headers:
243 243 self.will_close = (
244 244 headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE)
245 245 if (HDR_XFER_ENCODING in headers
246 246 and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED):
247 247 self._reader = _readers.ChunkedReader(self._eol)
248 248 logger.debug('using a chunked reader')
249 249 else:
250 250 # HEAD responses are forbidden from returning a body, and
251 251 # it's implausible for a CONNECT response to use
252 252 # close-is-end logic for an OK response.
253 253 if (self.method == 'HEAD' or
254 254 (self.method == 'CONNECT' and content_len is None)):
255 255 content_len = 0
256 256 if content_len is not None:
257 257 logger.debug('using a content-length reader with length %d',
258 258 content_len)
259 259 self._reader = _readers.ContentLengthReader(content_len)
260 260 else:
261 261 # Response body had no length specified and is not
262 262 # chunked, so the end of the body will only be
263 263 # identifiable by the termination of the socket by the
264 264 # server. My interpretation of the spec means that we
265 265 # are correct in hitting this case if
266 266 # transfer-encoding, content-length, and
267 267 # connection-control were left unspecified.
268 268 self._reader = _readers.CloseIsEndReader()
269 269 logger.debug('using a close-is-end reader')
270 270 self.will_close = True
271 271
272 272 if body:
273 273 # We're a friend of the reader class here.
274 274 # pylint: disable=W0212
275 275 self._reader._load(body)
276 276 logger.debug('headers complete')
277 277 self.headers = headers
278 278 # We're a friend of the reader class here.
279 279 # pylint: disable=W0212
280 280 self._load_response = self._reader._load
281 281
282 282
283 283 class HTTPConnection(object):
284 284 """Connection to a single http server.
285 285
286 286 Supports 100-continue and keepalives natively. Uses select() for
287 287 non-blocking socket operations.
288 288 """
289 289 http_version = HTTP_VER_1_1
290 290 response_class = HTTPResponse
291 291
292 292 def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
293 293 timeout=TIMEOUT_DEFAULT,
294 294 continue_timeout=TIMEOUT_ASSUME_CONTINUE,
295 proxy_hostport=None, **ssl_opts):
295 proxy_hostport=None, ssl_wrap_socket=None, **ssl_opts):
296 296 """Create a new HTTPConnection.
297 297
298 298 Args:
299 299 host: The host to which we'll connect.
300 300 port: Optional. The port over which we'll connect. Default 80 for
301 301 non-ssl, 443 for ssl.
302 302 use_ssl: Optional. Whether to use ssl. Defaults to False if port is
303 303 not 443, true if port is 443.
304 304 ssl_validator: a function(socket) to validate the ssl cert
305 305 timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
306 306 continue_timeout: Optional. Timeout for waiting on an expected
307 307 "100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
308 308 proxy_hostport: Optional. Tuple of (host, port) to use as an http
309 309 proxy for the connection. Default is to not use a proxy.
310 ssl_wrap_socket: Optional function to use for wrapping
311 sockets. If unspecified, the one from the ssl module will
312 be used if available, or something that's compatible with
313 it if on a Python older than 2.6.
314
315 Any extra keyword arguments to this function will be provided
316 to the ssl_wrap_socket method. If no ssl
310 317 """
311 318 if port is None and host.count(':') == 1 or ']:' in host:
312 319 host, port = host.rsplit(':', 1)
313 320 port = int(port)
314 321 if '[' in host:
315 322 host = host[1:-1]
323 if ssl_wrap_socket is not None:
324 self._ssl_wrap_socket = ssl_wrap_socket
325 else:
326 self._ssl_wrap_socket = socketutil.wrap_socket
316 327 if use_ssl is None and port is None:
317 328 use_ssl = False
318 329 port = 80
319 330 elif use_ssl is None:
320 331 use_ssl = (port == 443)
321 332 elif port is None:
322 333 port = (use_ssl and 443 or 80)
323 334 self.port = port
324 335 if use_ssl and not socketutil.have_ssl:
325 336 raise Exception('ssl requested but unavailable on this Python')
326 337 self.ssl = use_ssl
327 338 self.ssl_opts = ssl_opts
328 339 self._ssl_validator = ssl_validator
329 340 self.host = host
330 341 self.sock = None
331 342 self._current_response = None
332 343 self._current_response_taken = False
333 344 if proxy_hostport is None:
334 345 self._proxy_host = self._proxy_port = None
335 346 else:
336 347 self._proxy_host, self._proxy_port = proxy_hostport
337 348
338 349 self.timeout = timeout
339 350 self.continue_timeout = continue_timeout
340 351
341 352 def _connect(self):
342 353 """Connect to the host and port specified in __init__."""
343 354 if self.sock:
344 355 return
345 356 if self._proxy_host is not None:
346 357 logger.info('Connecting to http proxy %s:%s',
347 358 self._proxy_host, self._proxy_port)
348 359 sock = socketutil.create_connection((self._proxy_host,
349 360 self._proxy_port))
350 361 if self.ssl:
351 362 # TODO proxy header support
352 363 data = self._buildheaders('CONNECT', '%s:%d' % (self.host,
353 364 self.port),
354 365 {}, HTTP_VER_1_0)
355 366 sock.send(data)
356 367 sock.setblocking(0)
357 368 r = self.response_class(sock, self.timeout, 'CONNECT')
358 369 timeout_exc = HTTPTimeoutException(
359 370 'Timed out waiting for CONNECT response from proxy')
360 371 while not r.complete():
361 372 try:
362 373 # We're a friend of the response class, so let
363 374 # us use the private attribute.
364 375 # pylint: disable=W0212
365 376 if not r._select():
366 377 if not r.complete():
367 378 raise timeout_exc
368 379 except HTTPTimeoutException:
369 380 # This raise/except pattern looks goofy, but
370 381 # _select can raise the timeout as well as the
371 382 # loop body. I wish it wasn't this convoluted,
372 383 # but I don't have a better solution
373 384 # immediately handy.
374 385 raise timeout_exc
375 386 if r.status != 200:
376 387 raise HTTPProxyConnectFailedException(
377 388 'Proxy connection failed: %d %s' % (r.status,
378 389 r.read()))
379 390 logger.info('CONNECT (for SSL) to %s:%s via proxy succeeded.',
380 391 self.host, self.port)
381 392 else:
382 393 sock = socketutil.create_connection((self.host, self.port))
383 394 if self.ssl:
384 395 # This is the default, but in the case of proxied SSL
385 396 # requests the proxy logic above will have cleared
386 397 # blocking mode, so re-enable it just to be safe.
387 398 sock.setblocking(1)
388 399 logger.debug('wrapping socket for ssl with options %r',
389 400 self.ssl_opts)
390 sock = socketutil.wrap_socket(sock, **self.ssl_opts)
401 sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
391 402 if self._ssl_validator:
392 403 self._ssl_validator(sock)
393 404 sock.setblocking(0)
394 405 self.sock = sock
395 406
396 407 def _buildheaders(self, method, path, headers, http_ver):
397 408 if self.ssl and self.port == 443 or self.port == 80:
398 409 # default port for protocol, so leave it out
399 410 hdrhost = self.host
400 411 else:
401 412 # include nonstandard port in header
402 413 if ':' in self.host: # must be IPv6
403 414 hdrhost = '[%s]:%d' % (self.host, self.port)
404 415 else:
405 416 hdrhost = '%s:%d' % (self.host, self.port)
406 417 if self._proxy_host and not self.ssl:
407 418 # When talking to a regular http proxy we must send the
408 419 # full URI, but in all other cases we must not (although
409 420 # technically RFC 2616 says servers must accept our
410 421 # request if we screw up, experimentally few do that
411 422 # correctly.)
412 423 assert path[0] == '/', 'path must start with a /'
413 424 path = 'http://%s%s' % (hdrhost, path)
414 425 outgoing = ['%s %s %s%s' % (method, path, http_ver, EOL)]
415 426 headers['host'] = ('Host', hdrhost)
416 427 headers[HDR_ACCEPT_ENCODING] = (HDR_ACCEPT_ENCODING, 'identity')
417 428 for hdr, val in headers.itervalues():
418 429 outgoing.append('%s: %s%s' % (hdr, val, EOL))
419 430 outgoing.append(EOL)
420 431 return ''.join(outgoing)
421 432
422 433 def close(self):
423 434 """Close the connection to the server.
424 435
425 436 This is a no-op if the connection is already closed. The
426 437 connection may automatically close if requested by the server
427 438 or required by the nature of a response.
428 439 """
429 440 if self.sock is None:
430 441 return
431 442 self.sock.close()
432 443 self.sock = None
433 444 logger.info('closed connection to %s on %s', self.host, self.port)
434 445
435 446 def busy(self):
436 447 """Returns True if this connection object is currently in use.
437 448
438 449 If a response is still pending, this will return True, even if
439 450 the request has finished sending. In the future,
440 451 HTTPConnection may transparently juggle multiple connections
441 452 to the server, in which case this will be useful to detect if
442 453 any of those connections is ready for use.
443 454 """
444 455 cr = self._current_response
445 456 if cr is not None:
446 457 if self._current_response_taken:
447 458 if cr.will_close:
448 459 self.sock = None
449 460 self._current_response = None
450 461 return False
451 462 elif cr.complete():
452 463 self._current_response = None
453 464 return False
454 465 return True
455 466 return False
456 467
457 468 def _reconnect(self, where):
458 469 logger.info('reconnecting during %s', where)
459 470 self.close()
460 471 self._connect()
461 472
462 473 def request(self, method, path, body=None, headers={},
463 474 expect_continue=False):
464 475 """Send a request to the server.
465 476
466 477 For increased flexibility, this does not return the response
467 478 object. Future versions of HTTPConnection that juggle multiple
468 479 sockets will be able to send (for example) 5 requests all at
469 480 once, and then let the requests arrive as data is
470 481 available. Use the `getresponse()` method to retrieve the
471 482 response.
472 483 """
473 484 if self.busy():
474 485 raise httplib.CannotSendRequest(
475 486 'Can not send another request before '
476 487 'current response is read!')
477 488 self._current_response_taken = False
478 489
479 490 logger.info('sending %s request for %s to %s on port %s',
480 491 method, path, self.host, self.port)
481 492 hdrs = dict((k.lower(), (k, v)) for k, v in headers.iteritems())
482 493 if hdrs.get('expect', ('', ''))[1].lower() == '100-continue':
483 494 expect_continue = True
484 495 elif expect_continue:
485 496 hdrs['expect'] = ('Expect', '100-Continue')
486 497
487 498 chunked = False
488 499 if body and HDR_CONTENT_LENGTH not in hdrs:
489 500 if getattr(body, '__len__', False):
490 501 hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, len(body))
491 502 elif getattr(body, 'read', False):
492 503 hdrs[HDR_XFER_ENCODING] = (HDR_XFER_ENCODING,
493 504 XFER_ENCODING_CHUNKED)
494 505 chunked = True
495 506 else:
496 507 raise BadRequestData('body has no __len__() nor read()')
497 508
498 509 # If we're reusing the underlying socket, there are some
499 510 # conditions where we'll want to retry, so make a note of the
500 511 # state of self.sock
501 512 fresh_socket = self.sock is None
502 513 self._connect()
503 514 outgoing_headers = self._buildheaders(
504 515 method, path, hdrs, self.http_version)
505 516 response = None
506 517 first = True
507 518
508 519 while ((outgoing_headers or body)
509 520 and not (response and response.complete())):
510 521 select_timeout = self.timeout
511 522 out = outgoing_headers or body
512 523 blocking_on_continue = False
513 524 if expect_continue and not outgoing_headers and not (
514 525 response and (response.headers or response.continued)):
515 526 logger.info(
516 527 'waiting up to %s seconds for'
517 528 ' continue response from server',
518 529 self.continue_timeout)
519 530 select_timeout = self.continue_timeout
520 531 blocking_on_continue = True
521 532 out = False
522 533 if out:
523 534 w = [self.sock]
524 535 else:
525 536 w = []
526 537 r, w, x = select.select([self.sock], w, [], select_timeout)
527 538 # if we were expecting a 100 continue and it's been long
528 539 # enough, just go ahead and assume it's ok. This is the
529 540 # recommended behavior from the RFC.
530 541 if r == w == x == []:
531 542 if blocking_on_continue:
532 543 expect_continue = False
533 544 logger.info('no response to continue expectation from '
534 545 'server, optimistically sending request body')
535 546 else:
536 547 raise HTTPTimeoutException('timeout sending data')
537 548 was_first = first
538 549
539 550 # incoming data
540 551 if r:
541 552 try:
542 553 try:
543 554 data = r[0].recv(INCOMING_BUFFER_SIZE)
544 555 except socket.sslerror, e:
545 556 if e.args[0] != socket.SSL_ERROR_WANT_READ:
546 557 raise
547 558 logger.debug('SSL_ERROR_WANT_READ while sending '
548 559 'data, retrying...')
549 560 continue
550 561 if not data:
551 562 logger.info('socket appears closed in read')
552 563 self.sock = None
553 564 self._current_response = None
554 565 if response is not None:
555 566 # We're a friend of the response class, so let
556 567 # us use the private attribute.
557 568 # pylint: disable=W0212
558 569 response._close()
559 570 # This if/elif ladder is a bit subtle,
560 571 # comments in each branch should help.
561 572 if response is not None and response.complete():
562 573 # Server responded completely and then
563 574 # closed the socket. We should just shut
564 575 # things down and let the caller get their
565 576 # response.
566 577 logger.info('Got an early response, '
567 578 'aborting remaining request.')
568 579 break
569 580 elif was_first and response is None:
570 581 # Most likely a keepalive that got killed
571 582 # on the server's end. Commonly happens
572 583 # after getting a really large response
573 584 # from the server.
574 585 logger.info(
575 586 'Connection appeared closed in read on first'
576 587 ' request loop iteration, will retry.')
577 588 self._reconnect('read')
578 589 continue
579 590 else:
580 591 # We didn't just send the first data hunk,
581 592 # and either have a partial response or no
582 593 # response at all. There's really nothing
583 594 # meaningful we can do here.
584 595 raise HTTPStateError(
585 596 'Connection appears closed after '
586 597 'some request data was written, but the '
587 598 'response was missing or incomplete!')
588 599 logger.debug('read %d bytes in request()', len(data))
589 600 if response is None:
590 601 response = self.response_class(
591 602 r[0], self.timeout, method)
592 603 # We're a friend of the response class, so let us
593 604 # use the private attribute.
594 605 # pylint: disable=W0212
595 606 response._load_response(data)
596 607 # Jump to the next select() call so we load more
597 608 # data if the server is still sending us content.
598 609 continue
599 610 except socket.error, e:
600 611 if e[0] != errno.EPIPE and not was_first:
601 612 raise
602 613
603 614 # outgoing data
604 615 if w and out:
605 616 try:
606 617 if getattr(out, 'read', False):
607 618 # pylint guesses the type of out incorrectly here
608 619 # pylint: disable=E1103
609 620 data = out.read(OUTGOING_BUFFER_SIZE)
610 621 if not data:
611 622 continue
612 623 if len(data) < OUTGOING_BUFFER_SIZE:
613 624 if chunked:
614 625 body = '0' + EOL + EOL
615 626 else:
616 627 body = None
617 628 if chunked:
618 629 out = hex(len(data))[2:] + EOL + data + EOL
619 630 else:
620 631 out = data
621 632 amt = w[0].send(out)
622 633 except socket.error, e:
623 634 if e[0] == socket.SSL_ERROR_WANT_WRITE and self.ssl:
624 635 # This means that SSL hasn't flushed its buffer into
625 636 # the socket yet.
626 637 # TODO: find a way to block on ssl flushing its buffer
627 638 # similar to selecting on a raw socket.
628 639 continue
629 640 if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN:
630 641 continue
631 642 elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
632 643 and not first):
633 644 raise
634 645 self._reconnect('write')
635 646 amt = self.sock.send(out)
636 647 logger.debug('sent %d', amt)
637 648 first = False
638 649 if out is body:
639 650 body = out[amt:]
640 651 else:
641 652 outgoing_headers = out[amt:]
642 653
643 654 # close if the server response said to or responded before eating
644 655 # the whole request
645 656 if response is None:
646 657 response = self.response_class(self.sock, self.timeout, method)
647 658 if not fresh_socket:
648 659 if not response._select():
649 660 # This means the response failed to get any response
650 661 # data at all, and in all probability the socket was
651 662 # closed before the server even saw our request. Try
652 663 # the request again on a fresh socket.
653 664 logging.debug('response._select() failed during request().'
654 665 ' Assuming request needs to be retried.')
655 666 self.sock = None
656 667 # Call this method explicitly to re-try the
657 668 # request. We don't use self.request() because
658 669 # some tools (notably Mercurial) expect to be able
659 670 # to subclass and redefine request(), and they
660 671 # don't have the same argspec as we do.
661 672 #
662 673 # TODO restructure sending of requests to avoid
663 674 # this recursion
664 675 return HTTPConnection.request(
665 676 self, method, path, body=body, headers=headers,
666 677 expect_continue=expect_continue)
667 678 data_left = bool(outgoing_headers or body)
668 679 if data_left:
669 680 logger.info('stopped sending request early, '
670 681 'will close the socket to be safe.')
671 682 response.will_close = True
672 683 if response.will_close:
673 684 # The socket will be closed by the response, so we disown
674 685 # the socket
675 686 self.sock = None
676 687 self._current_response = response
677 688
678 689 def getresponse(self):
679 690 """Returns the response to the most recent request."""
680 691 if self._current_response is None:
681 692 raise httplib.ResponseNotReady()
682 693 r = self._current_response
683 694 while r.headers is None:
684 695 # We're a friend of the response class, so let us use the
685 696 # private attribute.
686 697 # pylint: disable=W0212
687 698 if not r._select() and not r.complete():
688 699 raise _readers.HTTPRemoteClosedError()
689 700 if r.will_close:
690 701 self.sock = None
691 702 self._current_response = None
692 703 elif r.complete():
693 704 self._current_response = None
694 705 else:
695 706 self._current_response_taken = True
696 707 return r
697 708
698 709
699 710 class HTTPTimeoutException(httplib.HTTPException):
700 711 """A timeout occurred while waiting on the server."""
701 712
702 713
703 714 class BadRequestData(httplib.HTTPException):
704 715 """Request body object has neither __len__ nor read."""
705 716
706 717
707 718 class HTTPProxyConnectFailedException(httplib.HTTPException):
708 719 """Connecting to the HTTP proxy failed."""
709 720
710 721
711 722 class HTTPStateError(httplib.HTTPException):
712 723 """Invalid internal state encountered."""
713 724
714 725 # Forward this exception type from _readers since it needs to be part
715 726 # of the public API.
716 727 HTTPRemoteClosedError = _readers.HTTPRemoteClosedError
717 728 # no-check-code
General Comments 0
You need to be logged in to leave comments. Login now