comparison mercurial/hgweb/hgweb_mod.py @ 36023:cdc93fe1da77

wireprotoserver: move protocol parsing and dispatch out of hgweb Previously, hgweb_mod had code for detecting if the request was for the wire protocol. It would then (eventually) call wireprotoserver.callhttp() to dispatch the request handling. Detection of wire protocol requests is not trivial. There's currently a big gotcha in the handling of the "cmd" request parameter, for example. Furthermore, in the near future we will have a second HTTP protocol handler. Its mechanism for calling commands will be a bit different. And we don't want the low-level logic for detecting protocol commands to live in hgweb. We establish a new function in wireprotoserver for detecting an HTTP protocol request and for giving the caller an easy-to-use mechanism for dispatching requests to it. Some wire protocol specific functionality still lives in hgweb. This will be addressed in subsequent commits. Differential Revision: https://phab.mercurial-scm.org/D2019
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 31 Jan 2018 16:21:43 -0800
parents 5a56bf4180ad
children e69e65b2b4a9
comparison
equal deleted inserted replaced
36022:f540b6448738 36023:cdc93fe1da77
355 query = '/'.join(parts) 355 query = '/'.join(parts)
356 else: 356 else:
357 query = req.env[r'QUERY_STRING'].partition(r'&')[0] 357 query = req.env[r'QUERY_STRING'].partition(r'&')[0]
358 query = query.partition(r';')[0] 358 query = query.partition(r';')[0]
359 359
360 # The ``cmd`` request parameter is used by both the wire protocol 360 # Route it to a wire protocol handler if it looks like a wire protocol
361 # and hgweb. We route all known wire protocol commands to the 361 # request.
362 # wire protocol handler, even if the command isn't available for 362 protohandler = wireprotoserver.parsehttprequest(rctx.repo, req, query)
363 # this transport. That's better for machine clients in the case 363
364 # of an errant request to an unavailable protocol command. And it 364 if protohandler:
365 # prevents hgweb from accidentally using ``cmd`` values used by 365 cmd = protohandler['cmd']
366 # the wire protocol.
367
368 # process this if it's a protocol request
369 # protocol bits don't need to create any URLs
370 # and the clients always use the old URL structure
371
372 cmd = pycompat.sysbytes(req.form.get(r'cmd', [r''])[0])
373 if wireprotoserver.iscmd(cmd):
374 try: 366 try:
375 if query: 367 if query:
376 raise ErrorResponse(HTTP_NOT_FOUND) 368 raise ErrorResponse(HTTP_NOT_FOUND)
377 if cmd in perms: 369 if cmd in perms:
378 self.check_perm(rctx, req, perms[cmd]) 370 self.check_perm(rctx, req, perms[cmd])
379 return wireprotoserver.callhttp(rctx.repo, req, cmd) 371 return protohandler['dispatch']()
380 except ErrorResponse as inst: 372 except ErrorResponse as inst:
381 # A client that sends unbundle without 100-continue will 373 # A client that sends unbundle without 100-continue will
382 # break if we respond early. 374 # break if we respond early.
383 if (cmd == 'unbundle' and 375 if (cmd == 'unbundle' and
384 (req.env.get('HTTP_EXPECT', 376 (req.env.get('HTTP_EXPECT',
423 for type_, spec in rctx.archivespecs.iteritems(): 415 for type_, spec in rctx.archivespecs.iteritems():
424 ext = spec[2] 416 ext = spec[2]
425 if fn.endswith(ext): 417 if fn.endswith(ext):
426 req.form['node'] = [fn[:-len(ext)]] 418 req.form['node'] = [fn[:-len(ext)]]
427 req.form['type'] = [type_] 419 req.form['type'] = [type_]
420 else:
421 cmd = pycompat.sysbytes(req.form.get(r'cmd', [r''])[0])
428 422
429 # process the web interface request 423 # process the web interface request
430 424
431 try: 425 try:
432 tmpl = rctx.templater(req) 426 tmpl = rctx.templater(req)