D2822: hgweb: support constructing URLs from an alternate base URL
This revision was automatically updated to reflect the committed changes. Closed by commit rHG219b23359f4c: hgweb: support constructing URLs from an alternate base URL (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D2822?vs=6888=6952 REVISION DETAIL https://phab.mercurial-scm.org/D2822 AFFECTED FILES mercurial/hgweb/hgwebdir_mod.py mercurial/hgweb/request.py tests/test-wsgirequest.py CHANGE DETAILS 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,12 @@ r'wsgi.run_once': False, } -def parse(env, bodyfh=None, reponame=None, extra=None): +def parse(env, bodyfh=None, reponame=None, altbaseurl=None, extra=None): env = dict(env) env.update(extra or {}) -return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame) +return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame, + altbaseurl=altbaseurl) class ParseRequestTests(unittest.TestCase): def testdefault(self): @@ -242,6 +243,174 @@ self.assertEqual(r.dispatchpath, b'path1/path2') self.assertEqual(r.reponame, b'prefix/repo') +def testaltbaseurl(self): +# Simple hostname remap. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver') + +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'http://altserver') +self.assertEqual(r.advertisedbaseurl, b'http://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With a custom port. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver:8000') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'http://altserver:8000') +self.assertEqual(r.advertisedbaseurl, b'http://altserver:8000') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With a changed protocol. +r = parse(DEFAULT_ENV, altbaseurl='https://altserver') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'https://altserver') +self.assertEqual(r.advertisedbaseurl, b'https://altserver') +# URL scheme is defined as the actual scheme, not advertised. +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# Need to specify explicit port number for proper https:// alt URLs. +r = parse(DEFAULT_ENV, altbaseurl='https://altserver:443') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'https://altserver') +self.assertEqual(r.advertisedbaseurl, b'https://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With only PATH_INFO defined. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver', extra={ +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://altserver/path1/path2') +self.assertEqual(r.advertisedbaseurl, b'http://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, [b'path1', b'path2']) +self.assertEqual(r.dispatchpath, b'path1/path2') +self.assertIsNone(r.reponame) + +# Path on alt URL. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altpath') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'http://altserver/altpath') +self.assertEqual(r.advertisedbaseurl, b'http://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'/altpath') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +
D2822: hgweb: support constructing URLs from an alternate base URL
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY The web.baseurl config option allows server operators to define a custom URL for hosted content. The way it works today is that hgwebdir parses this config option into URL components then updates the appropriate WSGI environment variables so the request "lies" about its details. For example, SERVER_NAME is updated to reflect the alternate base URL's hostname. The WSGI environment should not be modified because WSGI applications may want to know the original request details (for debugging, etc). This commit teaches our request parser about the existence of an alternate base URL. If defined, the advertised URL and other self-reflected paths will take the alternate base URL into account. The hgweb WSGI application didn't use web.baseurl. But hgwebdir did. We update hgwebdir to alter the environment parsing accordingly. The old code around environment manipulation has been removed. With this change, parserequestfromenv() has grown to a bit unwieldy. Now that practically everyone is using it, it is obvious that there is some unused features that can be trimmed. So look for this in follow-up commits. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D2822 AFFECTED FILES mercurial/hgweb/hgwebdir_mod.py mercurial/hgweb/request.py tests/test-wsgirequest.py CHANGE DETAILS 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,12 @@ r'wsgi.run_once': False, } -def parse(env, bodyfh=None, reponame=None, extra=None): +def parse(env, bodyfh=None, reponame=None, altbaseurl=None, extra=None): env = dict(env) env.update(extra or {}) -return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame) +return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame, + altbaseurl=altbaseurl) class ParseRequestTests(unittest.TestCase): def testdefault(self): @@ -242,6 +243,174 @@ self.assertEqual(r.dispatchpath, b'path1/path2') self.assertEqual(r.reponame, b'prefix/repo') +def testaltbaseurl(self): +# Simple hostname remap. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver') + +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'http://altserver') +self.assertEqual(r.advertisedbaseurl, b'http://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With a custom port. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver:8000') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'http://altserver:8000') +self.assertEqual(r.advertisedbaseurl, b'http://altserver:8000') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With a changed protocol. +r = parse(DEFAULT_ENV, altbaseurl='https://altserver') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'https://altserver') +self.assertEqual(r.advertisedbaseurl, b'https://altserver') +# URL scheme is defined as the actual scheme, not advertised. +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# Need to specify explicit port number for proper https:// alt URLs. +r = parse(DEFAULT_ENV, altbaseurl='https://altserver:443') +self.assertEqual(r.url, b'http://testserver') +self.assertEqual(r.baseurl, b'http://testserver') +self.assertEqual(r.advertisedurl, b'https://altserver') +self.assertEqual(r.advertisedbaseurl, b'https://altserver') +self.assertEqual(r.urlscheme, b'http') +self.assertEqual(r.apppath, b'') +self.assertEqual(r.dispatchparts, []) +self.assertIsNone(r.dispatchpath) +self.assertIsNone(r.reponame) + +# With only PATH_INFO defined. +r = parse(DEFAULT_ENV, altbaseurl='http://altserver', extra={ +r'PATH_INFO': r'/path1/path2', +}) +self.assertEqual(r.url, b'http://testserver/path1/path2') +