diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -369,18 +369,7 @@ class hgweb(object): if cmd in perms: self.check_perm(rctx, req, perms[cmd]) except ErrorResponse as inst: - # A client that sends unbundle without 100-continue will - # break if we respond early. - if (cmd == 'unbundle' and - (req.env.get('HTTP_EXPECT', - '').lower() != '100-continue') or - req.env.get('X-HgHttp2', '')): - req.drain() - else: - req.headers.append((r'Connection', r'Close')) - req.respond(inst, wireprotoserver.HGTYPE, - body='0\n%s\n' % inst) - return '' + return protohandler['handleerror'](inst) return protohandler['dispatch']() diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -242,6 +242,7 @@ def parsehttprequest(repo, req, query): 'cmd': cmd, 'proto': proto, 'dispatch': lambda: _callhttp(repo, req, proto, cmd), + 'handleerror': lambda ex: _handlehttperror(ex, req, cmd), } def _callhttp(repo, req, proto, cmd): @@ -303,6 +304,22 @@ def _callhttp(repo, req, proto, cmd): return [] raise error.ProgrammingError('hgweb.protocol internal failure', rsp) +def _handlehttperror(e, req, cmd): + """Called when an ErrorResponse is raised during HTTP request processing.""" + # A client that sends unbundle without 100-continue will + # break if we respond early. + if (cmd == 'unbundle' and + (req.env.get('HTTP_EXPECT', + '').lower() != '100-continue') or + req.env.get('X-HgHttp2', '')): + req.drain() + else: + req.headers.append((r'Connection', r'Close')) + + req.respond(e, HGTYPE, body='0\n%s\n' % e) + + return '' + class sshserver(abstractserverproto): def __init__(self, ui, repo): self._ui = ui