Show More
@@ -23,6 +23,9 b'' | |||
|
23 | 23 | # - import md5 function from a local util module |
|
24 | 24 | # Modified by Martin Geisler: |
|
25 | 25 | # - moved md5 function from local util module to this module |
|
26 | # Modified by Augie Fackler: | |
|
27 | # - add safesend method and use it to prevent broken pipe errors | |
|
28 | # on large POST requests | |
|
26 | 29 | |
|
27 | 30 | """An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive. |
|
28 | 31 | |
@@ -108,10 +111,11 b' EXTRA ATTRIBUTES AND METHODS' | |||
|
108 | 111 | |
|
109 | 112 | # $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $ |
|
110 | 113 | |
|
111 |
import |
|
|
114 | import errno | |
|
112 | 115 | import httplib |
|
113 | 116 | import socket |
|
114 | 117 | import thread |
|
118 | import urllib2 | |
|
115 | 119 | |
|
116 | 120 | DEBUG = None |
|
117 | 121 | |
@@ -495,10 +499,76 b' class HTTPResponse(httplib.HTTPResponse)' | |||
|
495 | 499 | break |
|
496 | 500 | return list |
|
497 | 501 | |
|
502 | def safesend(self, str): | |
|
503 | """Send `str' to the server. | |
|
504 | ||
|
505 | Shamelessly ripped off from httplib to patch a bad behavior. | |
|
506 | """ | |
|
507 | # _broken_pipe_resp is an attribute we set in this function | |
|
508 | # if the socket is closed while we're sending data but | |
|
509 | # the server sent us a response before hanging up. | |
|
510 | # In that case, we want to pretend to send the rest of the | |
|
511 | # outgoing data, and then let the user use getresponse() | |
|
512 | # (which we wrap) to get this last response before | |
|
513 | # opening a new socket. | |
|
514 | if getattr(self, '_broken_pipe_resp', None) is not None: | |
|
515 | return | |
|
516 | ||
|
517 | if self.sock is None: | |
|
518 | if self.auto_open: | |
|
519 | self.connect() | |
|
520 | else: | |
|
521 | raise httplib.NotConnected() | |
|
522 | ||
|
523 | # send the data to the server. if we get a broken pipe, then close | |
|
524 | # the socket. we want to reconnect when somebody tries to send again. | |
|
525 | # | |
|
526 | # NOTE: we DO propagate the error, though, because we cannot simply | |
|
527 | # ignore the error... the caller will know if they can retry. | |
|
528 | if self.debuglevel > 0: | |
|
529 | print "send:", repr(str) | |
|
530 | try: | |
|
531 | blocksize=8192 | |
|
532 | if hasattr(str,'read') : | |
|
533 | if self.debuglevel > 0: print "sendIng a read()able" | |
|
534 | data=str.read(blocksize) | |
|
535 | while data: | |
|
536 | self.sock.sendall(data) | |
|
537 | data=str.read(blocksize) | |
|
538 | else: | |
|
539 | self.sock.sendall(str) | |
|
540 | except socket.error, v: | |
|
541 | reraise = True | |
|
542 | if v[0] == errno.EPIPE: # Broken pipe | |
|
543 | if self._HTTPConnection__state == httplib._CS_REQ_SENT: | |
|
544 | self._broken_pipe_resp = None | |
|
545 | self._broken_pipe_resp = self.getresponse() | |
|
546 | reraise = False | |
|
547 | self.close() | |
|
548 | if reraise: | |
|
549 | raise | |
|
550 | ||
|
551 | def wrapgetresponse(cls): | |
|
552 | """Wraps getresponse in cls with a broken-pipe sane version. | |
|
553 | """ | |
|
554 | def safegetresponse(self): | |
|
555 | # In safesend() we might set the _broken_pipe_resp | |
|
556 | # attribute, in which case the socket has already | |
|
557 | # been closed and we just need to give them the response | |
|
558 | # back. Otherwise, we use the normal response path. | |
|
559 | r = getattr(self, '_broken_pipe_resp', None) | |
|
560 | if r is not None: | |
|
561 | return r | |
|
562 | return cls.getresponse(self) | |
|
563 | safegetresponse.__doc__ = cls.getresponse.__doc__ | |
|
564 | return safegetresponse | |
|
498 | 565 | |
|
499 | 566 | class HTTPConnection(httplib.HTTPConnection): |
|
500 | 567 | # use the modified response class |
|
501 | 568 | response_class = HTTPResponse |
|
569 | send = safesend | |
|
570 | getresponse = wrapgetresponse(httplib.HTTPConnection) | |
|
571 | ||
|
502 | 572 | |
|
503 | 573 | ######################################################################### |
|
504 | 574 | ##### TEST FUNCTIONS |
@@ -408,10 +408,14 b' class httphandler(keepalive.HTTPHandler)' | |||
|
408 | 408 | self.close_all() |
|
409 | 409 | |
|
410 | 410 | if has_https: |
|
411 |
class |
|
|
411 | class BetterHTTPS(httplib.HTTPSConnection): | |
|
412 | send = keepalive.safesend | |
|
413 | ||
|
414 | class httpsconnection(BetterHTTPS): | |
|
412 | 415 | response_class = keepalive.HTTPResponse |
|
413 | 416 | # must be able to send big bundle as stream. |
|
414 |
send = _gen_sendfile( |
|
|
417 | send = _gen_sendfile(BetterHTTPS) | |
|
418 | getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection) | |
|
415 | 419 | |
|
416 | 420 | class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler): |
|
417 | 421 | def __init__(self, ui): |
General Comments 0
You need to be logged in to leave comments.
Login now