D2818: tests: add test coverage for parsing WSGI requests
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Mon Mar 12 21:16:44 UTC 2018
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
A subsequent commit will need to make this code more complicated
in order to support alternate base URLs. Let's establish some test
coverage before we diverge too far from PEP 3333.
As part of this, a minor bug related to a missing SCRIPT_NAME
key has been squashed.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D2818
AFFECTED FILES
mercurial/hgweb/request.py
tests/test-wsgirequest.py
CHANGE DETAILS
diff --git a/tests/test-wsgirequest.py b/tests/test-wsgirequest.py
new file mode 100644
--- /dev/null
+++ b/tests/test-wsgirequest.py
@@ -0,0 +1,255 @@
+from __future__ import absolute_import, print_function
+
+import unittest
+
+from mercurial.hgweb import (
+ request as requestmod,
+)
+
+DEFAULT_ENV = {
+ r'REQUEST_METHOD': r'GET',
+ r'SERVER_NAME': r'testserver',
+ r'SERVER_PORT': r'80',
+ r'SERVER_PROTOCOL': r'http',
+ r'wsgi.version': (1, 0),
+ r'wsgi.url_scheme': r'http',
+ r'wsgi.input': None,
+ r'wsgi.errors': None,
+ r'wsgi.multithread': False,
+ r'wsgi.multiprocess': True,
+ r'wsgi.run_once': False,
+}
+
+def parse(env, bodyfh=None, extra=None):
+ env = dict(env)
+ env.update(extra or {})
+
+ return requestmod.parserequestfromenv(env, bodyfh)
+
+class ParseRequestTests(unittest.TestCase):
+ def testdefault(self):
+ r = parse(DEFAULT_ENV)
+ self.assertEqual(r.url, b'http://testserver')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.urlscheme, b'http')
+ self.assertEqual(r.method, b'GET')
+ self.assertIsNone(r.remoteuser)
+ self.assertIsNone(r.remotehost)
+ self.assertEqual(r.apppath, b'')
+ self.assertEqual(r.dispatchparts, [])
+ self.assertEqual(r.dispatchpath, b'')
+ self.assertFalse(r.havepathinfo)
+ self.assertIsNone(r.reponame)
+ self.assertEqual(r.querystring, b'')
+ self.assertEqual(len(r.qsparams), 0)
+ self.assertEqual(len(r.headers), 0)
+
+ def testcustomport(self):
+ r = parse(DEFAULT_ENV, extra={
+ r'SERVER_PORT': r'8000',
+ })
+
+ self.assertEqual(r.url, b'http://testserver:8000')
+ self.assertEqual(r.baseurl, b'http://testserver:8000')
+ self.assertEqual(r.advertisedurl, b'http://testserver:8000')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver:8000')
+
+ r = parse(DEFAULT_ENV, extra={
+ r'SERVER_PORT': r'4000',
+ r'wsgi.url_scheme': r'https',
+ })
+
+ self.assertEqual(r.url, b'https://testserver:4000')
+ self.assertEqual(r.baseurl, b'https://testserver:4000')
+ self.assertEqual(r.advertisedurl, b'https://testserver:4000')
+ self.assertEqual(r.advertisedbaseurl, b'https://testserver:4000')
+
+ def testhttphost(self):
+ r = parse(DEFAULT_ENV, extra={
+ r'HTTP_HOST': r'altserver',
+ })
+
+ self.assertEqual(r.url, b'http://altserver')
+ self.assertEqual(r.baseurl, b'http://altserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+
+ def testscriptname(self):
+ r = parse(DEFAULT_ENV, extra={
+ r'SCRIPT_NAME': r'',
+ })
+
+ self.assertEqual(r.url, b'http://testserver')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'')
+ self.assertEqual(r.dispatchparts, [])
+ self.assertEqual(r.dispatchpath, b'')
+ self.assertFalse(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'SCRIPT_NAME': r'/script',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/script')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/script')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/script')
+ self.assertEqual(r.dispatchparts, [])
+ self.assertEqual(r.dispatchpath, b'')
+ self.assertFalse(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'SCRIPT_NAME': r'/multiple words',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/multiple%20words')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/multiple%20words')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/multiple words')
+ self.assertEqual(r.dispatchparts, [])
+ self.assertEqual(r.dispatchpath, b'')
+ self.assertFalse(r.havepathinfo)
+
+ def testpathinfo(self):
+ r = parse(DEFAULT_ENV, extra={
+ r'PATH_INFO': r'',
+ })
+
+ self.assertEqual(r.url, b'http://testserver')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'')
+ self.assertEqual(r.dispatchparts, [])
+ self.assertEqual(r.dispatchpath, b'')
+ self.assertTrue(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'PATH_INFO': r'/pathinfo',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/pathinfo')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/pathinfo')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'')
+ self.assertEqual(r.dispatchparts, [b'pathinfo'])
+ self.assertEqual(r.dispatchpath, b'pathinfo')
+ self.assertTrue(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'PATH_INFO': r'/one/two/',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/one/two/')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/one/two/')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'')
+ self.assertEqual(r.dispatchparts, [b'one', b'two'])
+ self.assertEqual(r.dispatchpath, b'one/two')
+ self.assertTrue(r.havepathinfo)
+
+ def testscriptandpathinfo(self):
+ r = parse(DEFAULT_ENV, extra={
+ r'SCRIPT_NAME': r'/script',
+ r'PATH_INFO': r'/pathinfo',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/script/pathinfo')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/script/pathinfo')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/script')
+ self.assertEqual(r.dispatchparts, [b'pathinfo'])
+ self.assertEqual(r.dispatchpath, b'pathinfo')
+ self.assertTrue(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'SCRIPT_NAME': r'/script1/script2',
+ r'PATH_INFO': r'/path1/path2',
+ })
+
+ self.assertEqual(r.url,
+ b'http://testserver/script1/script2/path1/path2')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl,
+ b'http://testserver/script1/script2/path1/path2')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/script1/script2')
+ self.assertEqual(r.dispatchparts, [b'path1', b'path2'])
+ self.assertEqual(r.dispatchpath, b'path1/path2')
+ self.assertTrue(r.havepathinfo)
+
+ r = parse(DEFAULT_ENV, extra={
+ r'HTTP_HOST': r'hostserver',
+ r'SCRIPT_NAME': r'/script',
+ r'PATH_INFO': r'/pathinfo',
+ })
+
+ self.assertEqual(r.url, b'http://hostserver/script/pathinfo')
+ self.assertEqual(r.baseurl, b'http://hostserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/script/pathinfo')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/script')
+ self.assertEqual(r.dispatchparts, [b'pathinfo'])
+ self.assertEqual(r.dispatchpath, b'pathinfo')
+ self.assertTrue(r.havepathinfo)
+
+ def testreponame(self):
+ """REPO_NAME path components get stripped from URL."""
+ r = parse(DEFAULT_ENV, extra={
+ r'REPO_NAME': r'repo',
+ r'PATH_INFO': r'/path1/path2'
+ })
+
+ self.assertEqual(r.url, b'http://testserver/path1/path2')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/path1/path2')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/repo')
+ self.assertEqual(r.dispatchparts, [b'path1', b'path2'])
+ self.assertEqual(r.dispatchpath, b'path1/path2')
+ self.assertTrue(r.havepathinfo)
+ self.assertEqual(r.reponame, b'repo')
+
+ r = parse(DEFAULT_ENV, extra={
+ r'REPO_NAME': r'repo',
+ r'PATH_INFO': r'/repo/path1/path2',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/repo/path1/path2')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl, b'http://testserver/repo/path1/path2')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/repo')
+ self.assertEqual(r.dispatchparts, [b'path1', b'path2'])
+ self.assertEqual(r.dispatchpath, b'path1/path2')
+ self.assertTrue(r.havepathinfo)
+ self.assertEqual(r.reponame, b'repo')
+
+ r = parse(DEFAULT_ENV, extra={
+ r'REPO_NAME': r'prefix/repo',
+ r'PATH_INFO': r'/prefix/repo/path1/path2',
+ })
+
+ self.assertEqual(r.url, b'http://testserver/prefix/repo/path1/path2')
+ self.assertEqual(r.baseurl, b'http://testserver')
+ self.assertEqual(r.advertisedurl,
+ b'http://testserver/prefix/repo/path1/path2')
+ self.assertEqual(r.advertisedbaseurl, b'http://testserver')
+ self.assertEqual(r.apppath, b'/prefix/repo')
+ self.assertEqual(r.dispatchparts, [b'path1', b'path2'])
+ self.assertEqual(r.dispatchpath, b'path1/path2')
+ self.assertTrue(r.havepathinfo)
+ self.assertEqual(r.reponame, b'prefix/repo')
+
+if __name__ == '__main__':
+ import silenttestrunner
+ silenttestrunner.main(__name__)
diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -222,7 +222,7 @@
# root. We also exclude its path components from PATH_INFO when resolving
# the dispatch path.
- apppath = env['SCRIPT_NAME']
+ apppath = env.get('SCRIPT_NAME', '')
if env.get('REPO_NAME'):
if not apppath.endswith('/'):
To: indygreg, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list