Patchwork D2832: hgweb: remove wsgirequest (API)

login
register
mail settings
Submitter phabricator
Date March 12, 2018, 9:39 p.m.
Message ID <differential-rev-PHID-DREV-pmj4ws73gnih7wipobel-req@phab.mercurial-scm.org>
Download mbox | patch
Permalink /patch/29402/
State Superseded
Headers show

Comments

phabricator - March 12, 2018, 9:39 p.m.
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Good riddance.
  
  .. api::
  
    The old ``wsgirequest`` class for handling everything WSGI in hgweb
    has been replaced by separate request and response types. Various
    high-level functions in the hgweb WSGI applications now receive
    these new types as arguments instead of the old ``wsgirequest``
    type.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2832

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/hgweb/hgwebdir_mod.py
  mercurial/hgweb/request.py
  tests/test-wsgirequest.py

CHANGE DETAILS




To: indygreg, #hg-reviewers
Cc: mercurial-devel

Patch

diff --git a/tests/test-wsgirequest.py b/tests/test-wsgirequest.py
--- a/tests/test-wsgirequest.py
+++ b/tests/test-wsgirequest.py
@@ -23,11 +23,11 @@ 
     r'wsgi.run_once': False,
 }
 
-def parse(env, bodyfh=None, reponame=None, altbaseurl=None, extra=None):
+def parse(env, reponame=None, altbaseurl=None, extra=None):
     env = dict(env)
     env.update(extra or {})
 
-    return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame,
+    return requestmod.parserequestfromenv(env, reponame=reponame,
                                           altbaseurl=altbaseurl)
 
 class ParseRequestTests(unittest.TestCase):
diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -152,7 +152,7 @@ 
     # WSGI environment dict, unmodified.
     rawenv = attr.ib()
 
-def parserequestfromenv(env, bodyfh, reponame=None, altbaseurl=None):
+def parserequestfromenv(env, reponame=None, altbaseurl=None):
     """Parse URL components from environment variables.
 
     WSGI defines request attributes via environment variables. This function
@@ -325,11 +325,9 @@ 
     if 'CONTENT_LENGTH' in env and 'HTTP_CONTENT_LENGTH' not in env:
         headers['Content-Length'] = env['CONTENT_LENGTH']
 
-    # TODO do this once we remove wsgirequest.inp, otherwise we could have
-    # multiple readers from the underlying input stream.
-    #bodyfh = env['wsgi.input']
-    #if 'Content-Length' in headers:
-    #    bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length']))
+    bodyfh = env['wsgi.input']
+    if 'Content-Length' in headers:
+        bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length']))
 
     return parsedrequest(method=env['REQUEST_METHOD'],
                          url=fullurl, baseurl=baseurl,
@@ -578,34 +576,6 @@ 
         assert self._bodywritefn
         return offsettrackingwriter(self._bodywritefn)
 
-class wsgirequest(object):
-    """Higher-level API for a WSGI request.
-
-    WSGI applications are invoked with 2 arguments. They are used to
-    instantiate instances of this class, which provides higher-level APIs
-    for obtaining request parameters, writing HTTP output, etc.
-    """
-    def __init__(self, wsgienv, start_response, altbaseurl=None):
-        version = wsgienv[r'wsgi.version']
-        if (version < (1, 0)) or (version >= (2, 0)):
-            raise RuntimeError("Unknown and unsupported WSGI version %d.%d"
-                               % version)
-
-        inp = wsgienv[r'wsgi.input']
-
-        if r'HTTP_CONTENT_LENGTH' in wsgienv:
-            inp = util.cappedreader(inp, int(wsgienv[r'HTTP_CONTENT_LENGTH']))
-        elif r'CONTENT_LENGTH' in wsgienv:
-            inp = util.cappedreader(inp, int(wsgienv[r'CONTENT_LENGTH']))
-
-        self.err = wsgienv[r'wsgi.errors']
-        self.threaded = wsgienv[r'wsgi.multithread']
-        self.multiprocess = wsgienv[r'wsgi.multiprocess']
-        self.run_once = wsgienv[r'wsgi.run_once']
-        self.env = wsgienv
-        self.req = parserequestfromenv(wsgienv, inp, altbaseurl=altbaseurl)
-        self.res = wsgiresponse(self.req, start_response)
-
 def wsgiapplication(app_maker):
     '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir()
     can and should now be used as a WSGI application.'''
diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -348,19 +348,18 @@ 
 
     def __call__(self, env, respond):
         baseurl = self.ui.config('web', 'baseurl')
-        wsgireq = requestmod.wsgirequest(env, respond, altbaseurl=baseurl)
-        return self.run_wsgi(wsgireq)
+        req = requestmod.parserequestfromenv(env, altbaseurl=baseurl)
+        res = requestmod.wsgiresponse(req, respond)
 
-    def run_wsgi(self, wsgireq):
+        return self.run_wsgi(req, res)
+
+    def run_wsgi(self, req, res):
         profile = self.ui.configbool('profiling', 'enabled')
         with profiling.profile(self.ui, enabled=profile):
-            for r in self._runwsgi(wsgireq):
+            for r in self._runwsgi(req, res):
                 yield r
 
-    def _runwsgi(self, wsgireq):
-        req = wsgireq.req
-        res = wsgireq.res
-
+    def _runwsgi(self, req, res):
         try:
             self.refresh()
 
@@ -423,13 +422,13 @@ 
                 if real:
                     # Re-parse the WSGI environment to take into account our
                     # repository path component.
-                    wsgireq.req = requestmod.parserequestfromenv(
-                        wsgireq.env, wsgireq.req.bodyfh, reponame=virtualrepo,
+                    req = requestmod.parserequestfromenv(
+                        req.rawenv, reponame=virtualrepo,
                         altbaseurl=self.ui.config('web', 'baseurl'))
                     try:
                         # ensure caller gets private copy of ui
                         repo = hg.repository(self.ui.copy(), real)
-                        return hgweb_mod.hgweb(repo).run_wsgi(wsgireq)
+                        return hgweb_mod.hgweb(repo).run_wsgi(req, res)
                     except IOError as inst:
                         msg = encoding.strtolocal(inst.strerror)
                         raise ErrorResponse(HTTP_SERVER_ERROR, msg)
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -290,24 +290,24 @@ 
 
         This may be called by multiple threads.
         """
-        req = requestmod.wsgirequest(env, respond)
-        return self.run_wsgi(req)
+        req = requestmod.parserequestfromenv(env)
+        res = requestmod.wsgiresponse(req, respond)
 
-    def run_wsgi(self, wsgireq):
+        return self.run_wsgi(req, res)
+
+    def run_wsgi(self, req, res):
         """Internal method to run the WSGI application.
 
         This is typically only called by Mercurial. External consumers
         should be using instances of this class as the WSGI application.
         """
         with self._obtainrepo() as repo:
             profile = repo.ui.configbool('profiling', 'enabled')
             with profiling.profile(repo.ui, enabled=profile):
-                for r in self._runwsgi(wsgireq, repo):
+                for r in self._runwsgi(req, res, repo):
                     yield r
 
-    def _runwsgi(self, wsgireq, repo):
-        req = wsgireq.req
-        res = wsgireq.res
+    def _runwsgi(self, req, res, repo):
         rctx = requestcontext(self, repo, req, res)
 
         # This state is global across all threads.