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 @@ -357,6 +357,14 @@ query = req.env[r'QUERY_STRING'].partition(r'&')[0] query = query.partition(r';')[0] + # The ``cmd`` request parameter is used by both the wire protocol + # and hgweb. We route all known wire protocol commands to the + # wire protocol handler, even if the command isn't available for + # this transport. That's better for machine clients in the case + # of an errant request to an unavailable protocol command. And it + # prevents hgweb from accidentally using ``cmd`` values used by + # the wire protocol. + # process this if it's a protocol request # protocol bits don't need to create any URLs # and the clients always use the old URL structure diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -691,6 +691,12 @@ return super(commanddict, self).__setitem__(k, v) + def commandavailable(self, command, proto): + """Determine if a command is available for the requested protocol.""" + # For now, commands are available for all protocols. So do a simple + # membership test. + return command in self + commands = commanddict() def wireprotocommand(name, args=''): diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py --- a/mercurial/wireprotoserver.py +++ b/mercurial/wireprotoserver.py @@ -223,6 +223,13 @@ yield chunk rsp = wireproto.dispatch(repo, proto, cmd) + + if not wireproto.commands.commandavailable(cmd, proto): + req.respond(HTTP_OK, HGERRTYPE, + body=_('requested wire protocol command is not available ' + 'over HTTP')) + return [] + if isinstance(rsp, bytes): req.respond(HTTP_OK, HGTYPE, body=rsp) return [] @@ -351,7 +358,7 @@ def serve_one(self): cmd = self._fin.readline()[:-1] - if cmd and cmd in wireproto.commands: + if cmd and wireproto.commands.commandavailable(cmd, self): rsp = wireproto.dispatch(self._repo, self, cmd) self._handlers[rsp.__class__](self, rsp) elif cmd: