diff mercurial/hgweb/hgweb_mod.py @ 36876: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
line wrap: on
line diff
--- a/mercurial/hgweb/hgweb_mod.py	Sat Mar 10 14:19:27 2018 -0800
+++ b/mercurial/hgweb/hgweb_mod.py	Sat Mar 10 17:02:57 2018 -0800
@@ -91,9 +91,11 @@
     is prone to race conditions. Instances of this class exist to hold
     mutable and race-free state for requests.
     """
-    def __init__(self, app, repo):
+    def __init__(self, app, repo, req, res):
         self.repo = repo
         self.reponame = app.reponame
+        self.req = req
+        self.res = res
 
         self.archivespecs = archivespecs
 
@@ -305,7 +307,7 @@
     def _runwsgi(self, wsgireq, repo):
         req = wsgireq.req
         res = wsgireq.res
-        rctx = requestcontext(self, repo)
+        rctx = requestcontext(self, repo, req, res)
 
         # This state is global across all threads.
         encoding.encoding = rctx.config('web', 'encoding')
@@ -401,7 +403,15 @@
                 rctx.ctype = ctype
                 content = webcommands.rawfile(rctx, wsgireq, tmpl)
             else:
+                # Set some globals appropriate for web handlers. Commands can
+                # override easily enough.
+                res.status = '200 Script output follows'
+                res.headers['Content-Type'] = ctype
                 content = getattr(webcommands, cmd)(rctx, wsgireq, tmpl)
+
+                if content is res:
+                    return res.sendresponse()
+
                 wsgireq.respond(HTTP_OK, ctype)
 
             return content