##// END OF EJS Templates
httppeer: wrap HTTPResponse.read() globally...
Gregory Szorc -
r32002:bf855efe default
parent child Browse files
Show More
@@ -252,3 +252,6 class UnsupportedBundleSpecification(Exc
252 252
253 253 class CorruptedState(Exception):
254 254 """error raised when a command is not able to read its state from file"""
255
256 class RichIOError(Abort):
257 """An IOError that can also have a hint attached."""
@@ -75,6 +75,41 def encodevalueinheaders(value, header,
75 75
76 76 return result
77 77
78 def _wraphttpresponse(resp):
79 """Wrap an HTTPResponse with common error handlers.
80
81 This ensures that any I/O from any consumer raises the appropriate
82 error and messaging.
83 """
84 origread = resp.read
85
86 class readerproxy(resp.__class__):
87 def read(self, size=None):
88 try:
89 return origread(size)
90 except httplib.IncompleteRead as e:
91 # e.expected is an integer if length known or None otherwise.
92 if e.expected:
93 msg = _('HTTP request error (incomplete response; '
94 'expected %d bytes got %d)') % (e.expected,
95 len(e.partial))
96 else:
97 msg = _('HTTP request error (incomplete response)')
98
99 raise error.RichIOError(
100 msg,
101 hint=_('this may be an intermittent network failure; '
102 'if the error persists, consider contacting the '
103 'network or server operator'))
104 except httplib.HTTPException as e:
105 raise error.RichIOError(
106 _('HTTP request error (%s)') % e,
107 hint=_('this may be an intermittent failure; '
108 'if the error persists, consider contacting the '
109 'network or server operator'))
110
111 resp.__class__ = readerproxy
112
78 113 class httppeer(wireproto.wirepeer):
79 114 def __init__(self, ui, path):
80 115 self.path = path
@@ -223,6 +258,10 class httppeer(wireproto.wirepeer):
223 258 self.ui.debug('http error while sending %s command\n' % cmd)
224 259 self.ui.traceback()
225 260 raise IOError(None, inst)
261
262 # Insert error handlers for common I/O failures.
263 _wraphttpresponse(resp)
264
226 265 # record the url we got redirected to
227 266 resp_url = resp.geturl()
228 267 if resp_url.endswith(qs):
@@ -267,10 +267,10 Server sends an incomplete capabilities
267 267 $ hg --config badserver.closeaftersendbytes=180 serve -p $HGPORT -d --pid-file=hg.pid -E error.log
268 268 $ cat hg.pid > $DAEMON_PIDS
269 269
270 TODO client spews a stack due to uncaught httplib.IncompleteRead
271
272 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
273 [1]
270 $ hg clone http://localhost:$HGPORT/ clone
271 abort: HTTP request error (incomplete response; expected 385 bytes got 20)
272 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
273 [255]
274 274
275 275 $ killdaemons.py $DAEMON_PIDS
276 276
@@ -461,11 +461,11 Server sends empty HTTP body for getbund
461 461 $ hg --config badserver.closeaftersendbytes=933 serve -p $HGPORT -d --pid-file=hg.pid -E error.log
462 462 $ cat hg.pid > $DAEMON_PIDS
463 463
464 TODO client spews a stack due to uncaught httplib.IncompleteRead
465
466 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
464 $ hg clone http://localhost:$HGPORT/ clone
467 465 requesting all changes
468 [1]
466 abort: HTTP request error (incomplete response)
467 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
468 [255]
469 469
470 470 $ killdaemons.py $DAEMON_PIDS
471 471
@@ -525,11 +525,11 Server sends partial compression string
525 525 $ hg --config badserver.closeaftersendbytes=945 serve -p $HGPORT -d --pid-file=hg.pid -E error.log
526 526 $ cat hg.pid > $DAEMON_PIDS
527 527
528 TODO client spews a stack due to uncaught httplib.IncompleteRead
529
530 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
528 $ hg clone http://localhost:$HGPORT/ clone
531 529 requesting all changes
532 [1]
530 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
531 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
532 [255]
533 533
534 534 $ killdaemons.py $DAEMON_PIDS
535 535
@@ -593,7 +593,8 Server sends partial bundle2 header magi
593 593
594 594 $ hg clone http://localhost:$HGPORT/ clone
595 595 requesting all changes
596 abort: connection ended unexpectedly
596 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
597 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
597 598 [255]
598 599
599 600 $ killdaemons.py $DAEMON_PIDS
@@ -616,7 +617,8 Server sends incomplete bundle2 stream p
616 617
617 618 $ hg clone http://localhost:$HGPORT/ clone
618 619 requesting all changes
619 abort: connection ended unexpectedly
620 abort: HTTP request error (incomplete response; expected 1 bytes got 3)
621 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
620 622 [255]
621 623
622 624 $ killdaemons.py $DAEMON_PIDS
@@ -640,7 +642,8 Servers stops after bundle2 stream param
640 642
641 643 $ hg clone http://localhost:$HGPORT/ clone
642 644 requesting all changes
643 abort: connection ended unexpectedly
645 abort: HTTP request error (incomplete response)
646 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
644 647 [255]
645 648
646 649 $ killdaemons.py $DAEMON_PIDS
@@ -664,7 +667,8 Server stops sending after bundle2 part
664 667
665 668 $ hg clone http://localhost:$HGPORT/ clone
666 669 requesting all changes
667 abort: connection ended unexpectedly
670 abort: HTTP request error (incomplete response)
671 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
668 672 [255]
669 673
670 674 $ killdaemons.py $DAEMON_PIDS
@@ -785,7 +789,8 Server stops sending after 0 length payl
785 789 added 1 changesets with 1 changes to 1 files
786 790 transaction abort!
787 791 rollback completed
788 abort: connection ended unexpectedly
792 abort: HTTP request error (incomplete response)
793 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
789 794 [255]
790 795
791 796 $ killdaemons.py $DAEMON_PIDS
General Comments 0
You need to be logged in to leave comments. Login now