##// END OF EJS Templates
spelling: requested
timeless@mozdev.org -
r17536:dc6364a8 default
parent child Browse files
Show More
@@ -1,674 +1,674 b''
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 import cStringIO
41 41 import errno
42 42 import httplib
43 43 import logging
44 44 import rfc822
45 45 import select
46 46 import socket
47 47
48 48 import _readers
49 49 import socketutil
50 50
51 51 logger = logging.getLogger(__name__)
52 52
53 53 __all__ = ['HTTPConnection', 'HTTPResponse']
54 54
55 55 HTTP_VER_1_0 = 'HTTP/1.0'
56 56 HTTP_VER_1_1 = 'HTTP/1.1'
57 57
58 58 OUTGOING_BUFFER_SIZE = 1 << 15
59 59 INCOMING_BUFFER_SIZE = 1 << 20
60 60
61 61 HDR_ACCEPT_ENCODING = 'accept-encoding'
62 62 HDR_CONNECTION_CTRL = 'connection'
63 63 HDR_CONTENT_LENGTH = 'content-length'
64 64 HDR_XFER_ENCODING = 'transfer-encoding'
65 65
66 66 XFER_ENCODING_CHUNKED = 'chunked'
67 67
68 68 CONNECTION_CLOSE = 'close'
69 69
70 70 EOL = '\r\n'
71 71 _END_HEADERS = EOL * 2
72 72
73 73 # Based on some searching around, 1 second seems like a reasonable
74 74 # default here.
75 75 TIMEOUT_ASSUME_CONTINUE = 1
76 76 TIMEOUT_DEFAULT = None
77 77
78 78
79 79 class HTTPResponse(object):
80 80 """Response from an HTTP server.
81 81
82 82 The response will continue to load as available. If you need the
83 83 complete response before continuing, check the .complete() method.
84 84 """
85 85 def __init__(self, sock, timeout, method):
86 86 self.sock = sock
87 87 self.method = method
88 88 self.raw_response = ''
89 89 self._headers_len = 0
90 90 self.headers = None
91 91 self.will_close = False
92 92 self.status_line = ''
93 93 self.status = None
94 94 self.continued = False
95 95 self.http_version = None
96 96 self.reason = None
97 97 self._reader = None
98 98
99 99 self._read_location = 0
100 100 self._eol = EOL
101 101
102 102 self._timeout = timeout
103 103
104 104 @property
105 105 def _end_headers(self):
106 106 return self._eol * 2
107 107
108 108 def complete(self):
109 109 """Returns true if this response is completely loaded.
110 110
111 111 Note that if this is a connection where complete means the
112 112 socket is closed, this will nearly always return False, even
113 113 in cases where all the data has actually been loaded.
114 114 """
115 115 if self._reader:
116 116 return self._reader.done()
117 117
118 118 def _close(self):
119 119 if self._reader is not None:
120 120 self._reader._close()
121 121
122 122 def readline(self):
123 123 """Read a single line from the response body.
124 124
125 125 This may block until either a line ending is found or the
126 126 response is complete.
127 127 """
128 128 # TODO: move this into the reader interface where it can be
129 129 # smarter (and probably avoid copies)
130 130 bytes = []
131 131 while not bytes:
132 132 try:
133 133 bytes = [self._reader.read(1)]
134 134 except _readers.ReadNotReady:
135 135 self._select()
136 136 while bytes[-1] != '\n' and not self.complete():
137 137 self._select()
138 138 bytes.append(self._reader.read(1))
139 139 if bytes[-1] != '\n':
140 140 next = self._reader.read(1)
141 141 while next and next != '\n':
142 142 bytes.append(next)
143 143 next = self._reader.read(1)
144 144 bytes.append(next)
145 145 return ''.join(bytes)
146 146
147 147 def read(self, length=None):
148 148 # if length is None, unbounded read
149 149 while (not self.complete() # never select on a finished read
150 150 and (not length # unbounded, so we wait for complete()
151 151 or length > self._reader.available_data)):
152 152 self._select()
153 153 if not length:
154 154 length = self._reader.available_data
155 155 r = self._reader.read(length)
156 156 if self.complete() and self.will_close:
157 157 self.sock.close()
158 158 return r
159 159
160 160 def _select(self):
161 161 r, _, _ = select.select([self.sock], [], [], self._timeout)
162 162 if not r:
163 163 # socket was not readable. If the response is not
164 164 # complete, raise a timeout.
165 165 if not self.complete():
166 166 logger.info('timed out with timeout of %s', self._timeout)
167 167 raise HTTPTimeoutException('timeout reading data')
168 168 try:
169 169 data = self.sock.recv(INCOMING_BUFFER_SIZE)
170 170 except socket.sslerror, e:
171 171 if e.args[0] != socket.SSL_ERROR_WANT_READ:
172 172 raise
173 173 logger.debug('SSL_WANT_READ in _select, should retry later')
174 174 return True
175 175 logger.debug('response read %d data during _select', len(data))
176 176 # If the socket was readable and no data was read, that means
177 177 # the socket was closed. Inform the reader (if any) so it can
178 178 # raise an exception if this is an invalid situation.
179 179 if not data:
180 180 if self._reader:
181 181 self._reader._close()
182 182 return False
183 183 else:
184 184 self._load_response(data)
185 185 return True
186 186
187 187 def _load_response(self, data):
188 188 # Being here implies we're not at the end of the headers yet,
189 189 # since at the end of this method if headers were completely
190 190 # loaded we replace this method with the load() method of the
191 191 # reader we created.
192 192 self.raw_response += data
193 193 # This is a bogus server with bad line endings
194 194 if self._eol not in self.raw_response:
195 195 for bad_eol in ('\n', '\r'):
196 196 if (bad_eol in self.raw_response
197 197 # verify that bad_eol is not the end of the incoming data
198 198 # as this could be a response line that just got
199 199 # split between \r and \n.
200 200 and (self.raw_response.index(bad_eol) <
201 201 (len(self.raw_response) - 1))):
202 202 logger.info('bogus line endings detected, '
203 203 'using %r for EOL', bad_eol)
204 204 self._eol = bad_eol
205 205 break
206 206 # exit early if not at end of headers
207 207 if self._end_headers not in self.raw_response or self.headers:
208 208 return
209 209
210 210 # handle 100-continue response
211 211 hdrs, body = self.raw_response.split(self._end_headers, 1)
212 212 http_ver, status = hdrs.split(' ', 1)
213 213 if status.startswith('100'):
214 214 self.raw_response = body
215 215 self.continued = True
216 216 logger.debug('continue seen, setting body to %r', body)
217 217 return
218 218
219 219 # arriving here means we should parse response headers
220 220 # as all headers have arrived completely
221 221 hdrs, body = self.raw_response.split(self._end_headers, 1)
222 222 del self.raw_response
223 223 if self._eol in hdrs:
224 224 self.status_line, hdrs = hdrs.split(self._eol, 1)
225 225 else:
226 226 self.status_line = hdrs
227 227 hdrs = ''
228 228 # TODO HTTP < 1.0 support
229 229 (self.http_version, self.status,
230 230 self.reason) = self.status_line.split(' ', 2)
231 231 self.status = int(self.status)
232 232 if self._eol != EOL:
233 233 hdrs = hdrs.replace(self._eol, '\r\n')
234 234 headers = rfc822.Message(cStringIO.StringIO(hdrs))
235 235 content_len = None
236 236 if HDR_CONTENT_LENGTH in headers:
237 237 content_len = int(headers[HDR_CONTENT_LENGTH])
238 238 if self.http_version == HTTP_VER_1_0:
239 239 self.will_close = True
240 240 elif HDR_CONNECTION_CTRL in headers:
241 241 self.will_close = (
242 242 headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE)
243 243 if (HDR_XFER_ENCODING in headers
244 244 and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED):
245 245 self._reader = _readers.ChunkedReader(self._eol)
246 246 logger.debug('using a chunked reader')
247 247 else:
248 248 # HEAD responses are forbidden from returning a body, and
249 249 # it's implausible for a CONNECT response to use
250 250 # close-is-end logic for an OK response.
251 251 if (self.method == 'HEAD' or
252 252 (self.method == 'CONNECT' and content_len is None)):
253 253 content_len = 0
254 254 if content_len is not None:
255 255 logger.debug('using a content-length reader with length %d',
256 256 content_len)
257 257 self._reader = _readers.ContentLengthReader(content_len)
258 258 else:
259 259 # Response body had no length specified and is not
260 260 # chunked, so the end of the body will only be
261 261 # identifiable by the termination of the socket by the
262 262 # server. My interpretation of the spec means that we
263 263 # are correct in hitting this case if
264 264 # transfer-encoding, content-length, and
265 265 # connection-control were left unspecified.
266 266 self._reader = _readers.CloseIsEndReader()
267 267 logger.debug('using a close-is-end reader')
268 268 self.will_close = True
269 269
270 270 if body:
271 271 self._reader._load(body)
272 272 logger.debug('headers complete')
273 273 self.headers = headers
274 274 self._load_response = self._reader._load
275 275
276 276
277 277 class HTTPConnection(object):
278 278 """Connection to a single http server.
279 279
280 280 Supports 100-continue and keepalives natively. Uses select() for
281 281 non-blocking socket operations.
282 282 """
283 283 http_version = HTTP_VER_1_1
284 284 response_class = HTTPResponse
285 285
286 286 def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
287 287 timeout=TIMEOUT_DEFAULT,
288 288 continue_timeout=TIMEOUT_ASSUME_CONTINUE,
289 289 proxy_hostport=None, **ssl_opts):
290 290 """Create a new HTTPConnection.
291 291
292 292 Args:
293 293 host: The host to which we'll connect.
294 294 port: Optional. The port over which we'll connect. Default 80 for
295 295 non-ssl, 443 for ssl.
296 296 use_ssl: Optional. Wether to use ssl. Defaults to False if port is
297 297 not 443, true if port is 443.
298 298 ssl_validator: a function(socket) to validate the ssl cert
299 299 timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
300 300 continue_timeout: Optional. Timeout for waiting on an expected
301 301 "100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
302 302 proxy_hostport: Optional. Tuple of (host, port) to use as an http
303 303 proxy for the connection. Default is to not use a proxy.
304 304 """
305 305 if port is None and host.count(':') == 1 or ']:' in host:
306 306 host, port = host.rsplit(':', 1)
307 307 port = int(port)
308 308 if '[' in host:
309 309 host = host[1:-1]
310 310 if use_ssl is None and port is None:
311 311 use_ssl = False
312 312 port = 80
313 313 elif use_ssl is None:
314 314 use_ssl = (port == 443)
315 315 elif port is None:
316 316 port = (use_ssl and 443 or 80)
317 317 self.port = port
318 318 if use_ssl and not socketutil.have_ssl:
319 319 raise Exception('ssl requested but unavailable on this Python')
320 320 self.ssl = use_ssl
321 321 self.ssl_opts = ssl_opts
322 322 self._ssl_validator = ssl_validator
323 323 self.host = host
324 324 self.sock = None
325 325 self._current_response = None
326 326 self._current_response_taken = False
327 327 if proxy_hostport is None:
328 328 self._proxy_host = self._proxy_port = None
329 329 else:
330 330 self._proxy_host, self._proxy_port = proxy_hostport
331 331
332 332 self.timeout = timeout
333 333 self.continue_timeout = continue_timeout
334 334
335 335 def _connect(self):
336 336 """Connect to the host and port specified in __init__."""
337 337 if self.sock:
338 338 return
339 339 if self._proxy_host is not None:
340 340 logger.info('Connecting to http proxy %s:%s',
341 341 self._proxy_host, self._proxy_port)
342 342 sock = socketutil.create_connection((self._proxy_host,
343 343 self._proxy_port))
344 344 if self.ssl:
345 345 # TODO proxy header support
346 346 data = self.buildheaders('CONNECT', '%s:%d' % (self.host,
347 347 self.port),
348 348 {}, HTTP_VER_1_0)
349 349 sock.send(data)
350 350 sock.setblocking(0)
351 351 r = self.response_class(sock, self.timeout, 'CONNECT')
352 352 timeout_exc = HTTPTimeoutException(
353 353 'Timed out waiting for CONNECT response from proxy')
354 354 while not r.complete():
355 355 try:
356 356 if not r._select():
357 357 if not r.complete():
358 358 raise timeout_exc
359 359 except HTTPTimeoutException:
360 360 # This raise/except pattern looks goofy, but
361 361 # _select can raise the timeout as well as the
362 362 # loop body. I wish it wasn't this convoluted,
363 363 # but I don't have a better solution
364 364 # immediately handy.
365 365 raise timeout_exc
366 366 if r.status != 200:
367 367 raise HTTPProxyConnectFailedException(
368 368 'Proxy connection failed: %d %s' % (r.status,
369 369 r.read()))
370 370 logger.info('CONNECT (for SSL) to %s:%s via proxy succeeded.',
371 371 self.host, self.port)
372 372 else:
373 373 sock = socketutil.create_connection((self.host, self.port))
374 374 if self.ssl:
375 375 # This is the default, but in the case of proxied SSL
376 376 # requests the proxy logic above will have cleared
377 377 # blocking mode, so reenable it just to be safe.
378 378 sock.setblocking(1)
379 379 logger.debug('wrapping socket for ssl with options %r',
380 380 self.ssl_opts)
381 381 sock = socketutil.wrap_socket(sock, **self.ssl_opts)
382 382 if self._ssl_validator:
383 383 self._ssl_validator(sock)
384 384 sock.setblocking(0)
385 385 self.sock = sock
386 386
387 387 def buildheaders(self, method, path, headers, http_ver):
388 388 if self.ssl and self.port == 443 or self.port == 80:
389 389 # default port for protocol, so leave it out
390 390 hdrhost = self.host
391 391 else:
392 392 # include nonstandard port in header
393 393 if ':' in self.host: # must be IPv6
394 394 hdrhost = '[%s]:%d' % (self.host, self.port)
395 395 else:
396 396 hdrhost = '%s:%d' % (self.host, self.port)
397 397 if self._proxy_host and not self.ssl:
398 398 # When talking to a regular http proxy we must send the
399 399 # full URI, but in all other cases we must not (although
400 400 # technically RFC 2616 says servers must accept our
401 401 # request if we screw up, experimentally few do that
402 402 # correctly.)
403 403 assert path[0] == '/', 'path must start with a /'
404 404 path = 'http://%s%s' % (hdrhost, path)
405 405 outgoing = ['%s %s %s%s' % (method, path, http_ver, EOL)]
406 406 headers['host'] = ('Host', hdrhost)
407 407 headers[HDR_ACCEPT_ENCODING] = (HDR_ACCEPT_ENCODING, 'identity')
408 408 for hdr, val in headers.itervalues():
409 409 outgoing.append('%s: %s%s' % (hdr, val, EOL))
410 410 outgoing.append(EOL)
411 411 return ''.join(outgoing)
412 412
413 413 def close(self):
414 414 """Close the connection to the server.
415 415
416 416 This is a no-op if the connection is already closed. The
417 connection may automatically close if requessted by the server
417 connection may automatically close if requested by the server
418 418 or required by the nature of a response.
419 419 """
420 420 if self.sock is None:
421 421 return
422 422 self.sock.close()
423 423 self.sock = None
424 424 logger.info('closed connection to %s on %s', self.host, self.port)
425 425
426 426 def busy(self):
427 427 """Returns True if this connection object is currently in use.
428 428
429 429 If a response is still pending, this will return True, even if
430 430 the request has finished sending. In the future,
431 431 HTTPConnection may transparently juggle multiple connections
432 432 to the server, in which case this will be useful to detect if
433 433 any of those connections is ready for use.
434 434 """
435 435 cr = self._current_response
436 436 if cr is not None:
437 437 if self._current_response_taken:
438 438 if cr.will_close:
439 439 self.sock = None
440 440 self._current_response = None
441 441 return False
442 442 elif cr.complete():
443 443 self._current_response = None
444 444 return False
445 445 return True
446 446 return False
447 447
448 448 def request(self, method, path, body=None, headers={},
449 449 expect_continue=False):
450 450 """Send a request to the server.
451 451
452 452 For increased flexibility, this does not return the response
453 453 object. Future versions of HTTPConnection that juggle multiple
454 454 sockets will be able to send (for example) 5 requests all at
455 455 once, and then let the requests arrive as data is
456 456 available. Use the `getresponse()` method to retrieve the
457 457 response.
458 458 """
459 459 if self.busy():
460 460 raise httplib.CannotSendRequest(
461 461 'Can not send another request before '
462 462 'current response is read!')
463 463 self._current_response_taken = False
464 464
465 465 logger.info('sending %s request for %s to %s on port %s',
466 466 method, path, self.host, self.port)
467 467 hdrs = dict((k.lower(), (k, v)) for k, v in headers.iteritems())
468 468 if hdrs.get('expect', ('', ''))[1].lower() == '100-continue':
469 469 expect_continue = True
470 470 elif expect_continue:
471 471 hdrs['expect'] = ('Expect', '100-Continue')
472 472
473 473 chunked = False
474 474 if body and HDR_CONTENT_LENGTH not in hdrs:
475 475 if getattr(body, '__len__', False):
476 476 hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, len(body))
477 477 elif getattr(body, 'read', False):
478 478 hdrs[HDR_XFER_ENCODING] = (HDR_XFER_ENCODING,
479 479 XFER_ENCODING_CHUNKED)
480 480 chunked = True
481 481 else:
482 482 raise BadRequestData('body has no __len__() nor read()')
483 483
484 484 self._connect()
485 485 outgoing_headers = self.buildheaders(
486 486 method, path, hdrs, self.http_version)
487 487 response = None
488 488 first = True
489 489
490 490 def reconnect(where):
491 491 logger.info('reconnecting during %s', where)
492 492 self.close()
493 493 self._connect()
494 494
495 495 while ((outgoing_headers or body)
496 496 and not (response and response.complete())):
497 497 select_timeout = self.timeout
498 498 out = outgoing_headers or body
499 499 blocking_on_continue = False
500 500 if expect_continue and not outgoing_headers and not (
501 501 response and (response.headers or response.continued)):
502 502 logger.info(
503 503 'waiting up to %s seconds for'
504 504 ' continue response from server',
505 505 self.continue_timeout)
506 506 select_timeout = self.continue_timeout
507 507 blocking_on_continue = True
508 508 out = False
509 509 if out:
510 510 w = [self.sock]
511 511 else:
512 512 w = []
513 513 r, w, x = select.select([self.sock], w, [], select_timeout)
514 514 # if we were expecting a 100 continue and it's been long
515 515 # enough, just go ahead and assume it's ok. This is the
516 516 # recommended behavior from the RFC.
517 517 if r == w == x == []:
518 518 if blocking_on_continue:
519 519 expect_continue = False
520 520 logger.info('no response to continue expectation from '
521 521 'server, optimistically sending request body')
522 522 else:
523 523 raise HTTPTimeoutException('timeout sending data')
524 524 was_first = first
525 525
526 526 # incoming data
527 527 if r:
528 528 try:
529 529 try:
530 530 data = r[0].recv(INCOMING_BUFFER_SIZE)
531 531 except socket.sslerror, e:
532 532 if e.args[0] != socket.SSL_ERROR_WANT_READ:
533 533 raise
534 534 logger.debug(
535 535 'SSL_WANT_READ while sending data, retrying...')
536 536 continue
537 537 if not data:
538 538 logger.info('socket appears closed in read')
539 539 self.sock = None
540 540 self._current_response = None
541 541 if response is not None:
542 542 response._close()
543 543 # This if/elif ladder is a bit subtle,
544 544 # comments in each branch should help.
545 545 if response is not None and response.complete():
546 546 # Server responded completely and then
547 547 # closed the socket. We should just shut
548 548 # things down and let the caller get their
549 549 # response.
550 550 logger.info('Got an early response, '
551 551 'aborting remaining request.')
552 552 break
553 553 elif was_first and response is None:
554 554 # Most likely a keepalive that got killed
555 555 # on the server's end. Commonly happens
556 556 # after getting a really large response
557 557 # from the server.
558 558 logger.info(
559 559 'Connection appeared closed in read on first'
560 560 ' request loop iteration, will retry.')
561 561 reconnect('read')
562 562 continue
563 563 else:
564 564 # We didn't just send the first data hunk,
565 565 # and either have a partial response or no
566 566 # response at all. There's really nothing
567 567 # meaningful we can do here.
568 568 raise HTTPStateError(
569 569 'Connection appears closed after '
570 570 'some request data was written, but the '
571 571 'response was missing or incomplete!')
572 572 logger.debug('read %d bytes in request()', len(data))
573 573 if response is None:
574 574 response = self.response_class(r[0], self.timeout, method)
575 575 response._load_response(data)
576 576 # Jump to the next select() call so we load more
577 577 # data if the server is still sending us content.
578 578 continue
579 579 except socket.error, e:
580 580 if e[0] != errno.EPIPE and not was_first:
581 581 raise
582 582
583 583 # outgoing data
584 584 if w and out:
585 585 try:
586 586 if getattr(out, 'read', False):
587 587 data = out.read(OUTGOING_BUFFER_SIZE)
588 588 if not data:
589 589 continue
590 590 if len(data) < OUTGOING_BUFFER_SIZE:
591 591 if chunked:
592 592 body = '0' + EOL + EOL
593 593 else:
594 594 body = None
595 595 if chunked:
596 596 out = hex(len(data))[2:] + EOL + data + EOL
597 597 else:
598 598 out = data
599 599 amt = w[0].send(out)
600 600 except socket.error, e:
601 601 if e[0] == socket.SSL_ERROR_WANT_WRITE and self.ssl:
602 602 # This means that SSL hasn't flushed its buffer into
603 603 # the socket yet.
604 604 # TODO: find a way to block on ssl flushing its buffer
605 605 # similar to selecting on a raw socket.
606 606 continue
607 607 elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
608 608 and not first):
609 609 raise
610 610 reconnect('write')
611 611 amt = self.sock.send(out)
612 612 logger.debug('sent %d', amt)
613 613 first = False
614 614 # stash data we think we sent in case the socket breaks
615 615 # when we read from it
616 616 if was_first:
617 617 sent_data = out[:amt]
618 618 if out is body:
619 619 body = out[amt:]
620 620 else:
621 621 outgoing_headers = out[amt:]
622 622
623 623 # close if the server response said to or responded before eating
624 624 # the whole request
625 625 if response is None:
626 626 response = self.response_class(self.sock, self.timeout, method)
627 627 complete = response.complete()
628 628 data_left = bool(outgoing_headers or body)
629 629 if data_left:
630 630 logger.info('stopped sending request early, '
631 631 'will close the socket to be safe.')
632 632 response.will_close = True
633 633 if response.will_close:
634 634 # The socket will be closed by the response, so we disown
635 635 # the socket
636 636 self.sock = None
637 637 self._current_response = response
638 638
639 639 def getresponse(self):
640 640 if self._current_response is None:
641 641 raise httplib.ResponseNotReady()
642 642 r = self._current_response
643 643 while r.headers is None:
644 644 if not r._select() and not r.complete():
645 645 raise _readers.HTTPRemoteClosedError()
646 646 if r.will_close:
647 647 self.sock = None
648 648 self._current_response = None
649 649 elif r.complete():
650 650 self._current_response = None
651 651 else:
652 652 self._current_response_taken = True
653 653 return r
654 654
655 655
656 656 class HTTPTimeoutException(httplib.HTTPException):
657 657 """A timeout occurred while waiting on the server."""
658 658
659 659
660 660 class BadRequestData(httplib.HTTPException):
661 661 """Request body object has neither __len__ nor read."""
662 662
663 663
664 664 class HTTPProxyConnectFailedException(httplib.HTTPException):
665 665 """Connecting to the HTTP proxy failed."""
666 666
667 667
668 668 class HTTPStateError(httplib.HTTPException):
669 669 """Invalid internal state encountered."""
670 670
671 671 # Forward this exception type from _readers since it needs to be part
672 672 # of the public API.
673 673 HTTPRemoteClosedError = _readers.HTTPRemoteClosedError
674 674 # no-check-code
General Comments 0
You need to be logged in to leave comments. Login now