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,10 +290,12 @@ class hgweb(object): 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 @@ -302,12 +304,10 @@ class hgweb(object): 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. 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 @@ class hgwebdir(object): 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 @@ class hgwebdir(object): 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/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -152,7 +152,7 @@ class parsedrequest(object): # 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 @@ def parserequestfromenv(env, bodyfh, rep 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 @@ class wsgiresponse(object): 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/tests/test-wsgirequest.py b/tests/test-wsgirequest.py --- a/tests/test-wsgirequest.py +++ b/tests/test-wsgirequest.py @@ -23,11 +23,11 @@ DEFAULT_ENV = { 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):