diff -r f540b6448738 -r cdc93fe1da77 mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py Thu Feb 01 18:48:52 2018 -0800 +++ b/mercurial/wireprotoserver.py Wed Jan 31 16:21:43 2018 -0800 @@ -208,9 +208,43 @@ def iscmd(cmd): return cmd in wireproto.commands -def callhttp(repo, req, cmd): +def parsehttprequest(repo, req, query): + """Parse the HTTP request for a wire protocol request. + + If the current request appears to be a wire protocol request, this + function returns a dict with details about that request, including + an ``abstractprotocolserver`` instance suitable for handling the + request. Otherwise, ``None`` is returned. + + ``req`` is a ``wsgirequest`` instance. + """ + # HTTP version 1 wire protocol requests are denoted by a "cmd" query + # string parameter. If it isn't present, this isn't a wire protocol + # request. + if r'cmd' not in req.form: + return None + + cmd = pycompat.sysbytes(req.form[r'cmd'][0]) + + # The "cmd" request parameter is used by both the wire protocol and hgweb. + # While not all wire protocol commands are available for all transports, + # if we see a "cmd" value that resembles a known wire protocol command, we + # route it to a protocol handler. This is better than routing possible + # wire protocol requests to hgweb because it prevents hgweb from using + # known wire protocol commands and it is less confusing for machine + # clients. + if cmd not in wireproto.commands: + return None + proto = webproto(req, repo.ui) + return { + 'cmd': cmd, + 'proto': proto, + 'dispatch': lambda: _callhttp(repo, req, proto, cmd), + } + +def _callhttp(repo, req, proto, cmd): def genversion2(gen, engine, engineopts): # application/mercurial-0.2 always sends a payload header # identifying the compression engine.