Mercurial > public > mercurial-scm > hg-stable
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) |