Mercurial > public > mercurial-scm > hg
comparison mercurial/hgweb/hgweb_mod.py @ 36870:1f42d621f090
hgweb: support using new response object for web commands
We have a "requestcontext" type for holding state for the current
request. Why we pass in the wsgirequest and templater instance
to @webcommand functions, I don't know.
I like the idea of standardizing on using "requestcontext" for passing
all state to @webcommand functions because that scales well without
API changes every time you want to pass a new piece of data. So,
we add our new request and response instances to "requestcontext" so
@webcommand functions can access them.
We also teach our command dispatcher to recognize a new calling
convention. Instead of returning content from the @webcommand
function, we return our response object. This signals that this
response object is to be used for sending output. The keyword
extension was wrapping various @webcommand and assuming the output
was iterable, so we had to teach it about the new calling convention.
To prove everything works, we convert the "filelog" @webcommand
to use the new convention.
The new calling convention is a bit wonky. I intend to improve this
once all commands are ported to use the new response object.
Differential Revision: https://phab.mercurial-scm.org/D2786
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 10 Mar 2018 17:02:57 -0800 |
parents | 7ad6a275316f |
children | 9fc3d814646e |
comparison
equal
deleted
inserted
replaced
36869:7ad6a275316f | 36870:1f42d621f090 |
---|---|
89 | 89 |
90 Servers can be multi-threaded. Holding state on the WSGI application | 90 Servers can be multi-threaded. Holding state on the WSGI application |
91 is prone to race conditions. Instances of this class exist to hold | 91 is prone to race conditions. Instances of this class exist to hold |
92 mutable and race-free state for requests. | 92 mutable and race-free state for requests. |
93 """ | 93 """ |
94 def __init__(self, app, repo): | 94 def __init__(self, app, repo, req, res): |
95 self.repo = repo | 95 self.repo = repo |
96 self.reponame = app.reponame | 96 self.reponame = app.reponame |
97 self.req = req | |
98 self.res = res | |
97 | 99 |
98 self.archivespecs = archivespecs | 100 self.archivespecs = archivespecs |
99 | 101 |
100 self.maxchanges = self.configint('web', 'maxchanges') | 102 self.maxchanges = self.configint('web', 'maxchanges') |
101 self.stripecount = self.configint('web', 'stripes') | 103 self.stripecount = self.configint('web', 'stripes') |
303 yield r | 305 yield r |
304 | 306 |
305 def _runwsgi(self, wsgireq, repo): | 307 def _runwsgi(self, wsgireq, repo): |
306 req = wsgireq.req | 308 req = wsgireq.req |
307 res = wsgireq.res | 309 res = wsgireq.res |
308 rctx = requestcontext(self, repo) | 310 rctx = requestcontext(self, repo, req, res) |
309 | 311 |
310 # This state is global across all threads. | 312 # This state is global across all threads. |
311 encoding.encoding = rctx.config('web', 'encoding') | 313 encoding.encoding = rctx.config('web', 'encoding') |
312 rctx.repo.ui.environ = wsgireq.env | 314 rctx.repo.ui.environ = wsgireq.env |
313 | 315 |
399 raise ErrorResponse(HTTP_BAD_REQUEST, msg) | 401 raise ErrorResponse(HTTP_BAD_REQUEST, msg) |
400 elif cmd == 'file' and req.qsparams.get('style') == 'raw': | 402 elif cmd == 'file' and req.qsparams.get('style') == 'raw': |
401 rctx.ctype = ctype | 403 rctx.ctype = ctype |
402 content = webcommands.rawfile(rctx, wsgireq, tmpl) | 404 content = webcommands.rawfile(rctx, wsgireq, tmpl) |
403 else: | 405 else: |
406 # Set some globals appropriate for web handlers. Commands can | |
407 # override easily enough. | |
408 res.status = '200 Script output follows' | |
409 res.headers['Content-Type'] = ctype | |
404 content = getattr(webcommands, cmd)(rctx, wsgireq, tmpl) | 410 content = getattr(webcommands, cmd)(rctx, wsgireq, tmpl) |
411 | |
412 if content is res: | |
413 return res.sendresponse() | |
414 | |
405 wsgireq.respond(HTTP_OK, ctype) | 415 wsgireq.respond(HTTP_OK, ctype) |
406 | 416 |
407 return content | 417 return content |
408 | 418 |
409 except (error.LookupError, error.RepoLookupError) as err: | 419 except (error.LookupError, error.RepoLookupError) as err: |