mercurial/wireprotoserver.py
changeset 37047 fddcb51b5084
parent 37046 1cfef5693203
child 37048 fc5e261915b9
equal deleted inserted replaced
37046:1cfef5693203 37047:fddcb51b5084
   270 
   270 
   271     API_HANDLERS[proto]['handler'](rctx, req, res, checkperm,
   271     API_HANDLERS[proto]['handler'](rctx, req, res, checkperm,
   272                                    req.dispatchparts[2:])
   272                                    req.dispatchparts[2:])
   273 
   273 
   274 def _handlehttpv2request(rctx, req, res, checkperm, urlparts):
   274 def _handlehttpv2request(rctx, req, res, checkperm, urlparts):
       
   275     from .hgweb import common as hgwebcommon
       
   276 
       
   277     # URL space looks like: <permissions>/<command>, where <permission> can
       
   278     # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
       
   279 
       
   280     # Root URL does nothing meaningful... yet.
       
   281     if not urlparts:
       
   282         res.status = b'200 OK'
       
   283         res.headers[b'Content-Type'] = b'text/plain'
       
   284         res.setbodybytes(_('HTTP version 2 API handler'))
       
   285         return
       
   286 
       
   287     if len(urlparts) == 1:
       
   288         res.status = b'404 Not Found'
       
   289         res.headers[b'Content-Type'] = b'text/plain'
       
   290         res.setbodybytes(_('do not know how to process %s\n') %
       
   291                          req.dispatchpath)
       
   292         return
       
   293 
       
   294     permission, command = urlparts[0:2]
       
   295 
       
   296     if permission not in (b'ro', b'rw'):
       
   297         res.status = b'404 Not Found'
       
   298         res.headers[b'Content-Type'] = b'text/plain'
       
   299         res.setbodybytes(_('unknown permission: %s') % permission)
       
   300         return
       
   301 
       
   302     # At some point we'll want to use our own API instead of recycling the
       
   303     # behavior of version 1 of the wire protocol...
       
   304     # TODO return reasonable responses - not responses that overload the
       
   305     # HTTP status line message for error reporting.
       
   306     try:
       
   307         checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
       
   308     except hgwebcommon.ErrorResponse as e:
       
   309         res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
       
   310         for k, v in e.headers:
       
   311             res.headers[k] = v
       
   312         res.setbodybytes('permission denied')
       
   313         return
       
   314 
       
   315     if command not in wireproto.commands:
       
   316         res.status = b'404 Not Found'
       
   317         res.headers[b'Content-Type'] = b'text/plain'
       
   318         res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
       
   319         return
       
   320 
       
   321     repo = rctx.repo
       
   322     ui = repo.ui
       
   323 
       
   324     proto = httpv2protocolhandler(req, ui)
       
   325 
       
   326     if not wireproto.commands.commandavailable(command, proto):
       
   327         res.status = b'404 Not Found'
       
   328         res.headers[b'Content-Type'] = b'text/plain'
       
   329         res.setbodybytes(_('invalid wire protocol command: %s') % command)
       
   330         return
       
   331 
       
   332     # We don't do anything meaningful yet.
   275     res.status = b'200 OK'
   333     res.status = b'200 OK'
   276     res.headers[b'Content-Type'] = b'text/plain'
   334     res.headers[b'Content-Type'] = b'text/plain'
   277     res.setbodybytes(b'/'.join(urlparts) + b'\n')
   335     res.setbodybytes(b'/'.join(urlparts) + b'\n')
   278 
   336 
   279 # Maps API name to metadata so custom API can be registered.
   337 # Maps API name to metadata so custom API can be registered.
   281     HTTPV2: {
   339     HTTPV2: {
   282         'config': ('experimental', 'web.api.http-v2'),
   340         'config': ('experimental', 'web.api.http-v2'),
   283         'handler': _handlehttpv2request,
   341         'handler': _handlehttpv2request,
   284     },
   342     },
   285 }
   343 }
       
   344 
       
   345 class httpv2protocolhandler(wireprototypes.baseprotocolhandler):
       
   346     def __init__(self, req, ui):
       
   347         self._req = req
       
   348         self._ui = ui
       
   349 
       
   350     @property
       
   351     def name(self):
       
   352         return HTTPV2
       
   353 
       
   354     def getargs(self, args):
       
   355         raise NotImplementedError
       
   356 
       
   357     def forwardpayload(self, fp):
       
   358         raise NotImplementedError
       
   359 
       
   360     @contextlib.contextmanager
       
   361     def mayberedirectstdio(self):
       
   362         raise NotImplementedError
       
   363 
       
   364     def client(self):
       
   365         raise NotImplementedError
       
   366 
       
   367     def addcapabilities(self, repo, caps):
       
   368         raise NotImplementedError
       
   369 
       
   370     def checkperm(self, perm):
       
   371         raise NotImplementedError
   286 
   372 
   287 def _httpresponsetype(ui, req, prefer_uncompressed):
   373 def _httpresponsetype(ui, req, prefer_uncompressed):
   288     """Determine the appropriate response type and compression settings.
   374     """Determine the appropriate response type and compression settings.
   289 
   375 
   290     Returns a tuple of (mediatype, compengine, engineopts).
   376     Returns a tuple of (mediatype, compengine, engineopts).