Show More
@@ -33,7 +33,6 from .. import ( | |||||
33 | error, |
|
33 | error, | |
34 | hg, |
|
34 | hg, | |
35 | profiling, |
|
35 | profiling, | |
36 | pycompat, |
|
|||
37 | scmutil, |
|
36 | scmutil, | |
38 | templater, |
|
37 | templater, | |
39 | ui as uimod, |
|
38 | ui as uimod, | |
@@ -83,33 +82,6 def urlrepos(prefix, roothead, paths): | |||||
83 | yield (prefix + '/' + |
|
82 | yield (prefix + '/' + | |
84 | util.pconvert(path[len(roothead):]).lstrip('/')).strip('/'), path |
|
83 | util.pconvert(path[len(roothead):]).lstrip('/')).strip('/'), path | |
85 |
|
84 | |||
86 | def geturlcgivars(baseurl, port): |
|
|||
87 | """ |
|
|||
88 | Extract CGI variables from baseurl |
|
|||
89 |
|
||||
90 | >>> geturlcgivars(b"http://host.org/base", b"80") |
|
|||
91 | ('host.org', '80', '/base') |
|
|||
92 | >>> geturlcgivars(b"http://host.org:8000/base", b"80") |
|
|||
93 | ('host.org', '8000', '/base') |
|
|||
94 | >>> geturlcgivars(b'/base', 8000) |
|
|||
95 | ('', '8000', '/base') |
|
|||
96 | >>> geturlcgivars(b"base", b'8000') |
|
|||
97 | ('', '8000', '/base') |
|
|||
98 | >>> geturlcgivars(b"http://host", b'8000') |
|
|||
99 | ('host', '8000', '/') |
|
|||
100 | >>> geturlcgivars(b"http://host/", b'8000') |
|
|||
101 | ('host', '8000', '/') |
|
|||
102 | """ |
|
|||
103 | u = util.url(baseurl) |
|
|||
104 | name = u.host or '' |
|
|||
105 | if u.port: |
|
|||
106 | port = u.port |
|
|||
107 | path = u.path or "" |
|
|||
108 | if not path.startswith('/'): |
|
|||
109 | path = '/' + path |
|
|||
110 |
|
||||
111 | return name, pycompat.bytestr(port), path |
|
|||
112 |
|
||||
113 | def readallowed(ui, req): |
|
85 | def readallowed(ui, req): | |
114 | """Check allow_read and deny_read config options of a repo's ui object |
|
86 | """Check allow_read and deny_read config options of a repo's ui object | |
115 | to determine user permissions. By default, with neither option set (or |
|
87 | to determine user permissions. By default, with neither option set (or | |
@@ -359,7 +331,6 class hgwebdir(object): | |||||
359 | self.stripecount = self.ui.config('web', 'stripes') |
|
331 | self.stripecount = self.ui.config('web', 'stripes') | |
360 | if self.stripecount: |
|
332 | if self.stripecount: | |
361 | self.stripecount = int(self.stripecount) |
|
333 | self.stripecount = int(self.stripecount) | |
362 | self._baseurl = self.ui.config('web', 'baseurl') |
|
|||
363 | prefix = self.ui.config('web', 'prefix') |
|
334 | prefix = self.ui.config('web', 'prefix') | |
364 | if prefix.startswith('/'): |
|
335 | if prefix.startswith('/'): | |
365 | prefix = prefix[1:] |
|
336 | prefix = prefix[1:] | |
@@ -376,7 +347,8 class hgwebdir(object): | |||||
376 | wsgicgi.launch(self) |
|
347 | wsgicgi.launch(self) | |
377 |
|
348 | |||
378 | def __call__(self, env, respond): |
|
349 | def __call__(self, env, respond): | |
379 | wsgireq = requestmod.wsgirequest(env, respond) |
|
350 | baseurl = self.ui.config('web', 'baseurl') | |
|
351 | wsgireq = requestmod.wsgirequest(env, respond, altbaseurl=baseurl) | |||
380 | return self.run_wsgi(wsgireq) |
|
352 | return self.run_wsgi(wsgireq) | |
381 |
|
353 | |||
382 | def run_wsgi(self, wsgireq): |
|
354 | def run_wsgi(self, wsgireq): | |
@@ -455,7 +427,8 class hgwebdir(object): | |||||
455 | # Re-parse the WSGI environment to take into account our |
|
427 | # Re-parse the WSGI environment to take into account our | |
456 | # repository path component. |
|
428 | # repository path component. | |
457 | wsgireq.req = requestmod.parserequestfromenv( |
|
429 | wsgireq.req = requestmod.parserequestfromenv( | |
458 |
wsgireq.env, wsgireq.req.bodyfh, reponame=virtualrepo |
|
430 | wsgireq.env, wsgireq.req.bodyfh, reponame=virtualrepo, | |
|
431 | altbaseurl=self.ui.config('web', 'baseurl')) | |||
459 | try: |
|
432 | try: | |
460 | # ensure caller gets private copy of ui |
|
433 | # ensure caller gets private copy of ui | |
461 | repo = hg.repository(self.ui.copy(), real) |
|
434 | repo = hg.repository(self.ui.copy(), real) | |
@@ -502,7 +475,6 class hgwebdir(object): | |||||
502 | for column in sortable] |
|
475 | for column in sortable] | |
503 |
|
476 | |||
504 | self.refresh() |
|
477 | self.refresh() | |
505 | self.updatereqenv(wsgireq.env) |
|
|||
506 |
|
478 | |||
507 | entries = indexentries(self.ui, self.repos, wsgireq, req, |
|
479 | entries = indexentries(self.ui, self.repos, wsgireq, req, | |
508 | self.stripecount, sortcolumn=sortcolumn, |
|
480 | self.stripecount, sortcolumn=sortcolumn, | |
@@ -524,8 +496,6 class hgwebdir(object): | |||||
524 | def config(section, name, default=uimod._unset, untrusted=True): |
|
496 | def config(section, name, default=uimod._unset, untrusted=True): | |
525 | return self.ui.config(section, name, default, untrusted) |
|
497 | return self.ui.config(section, name, default, untrusted) | |
526 |
|
498 | |||
527 | self.updatereqenv(wsgireq.env) |
|
|||
528 |
|
||||
529 | url = wsgireq.env.get('SCRIPT_NAME', '') |
|
499 | url = wsgireq.env.get('SCRIPT_NAME', '') | |
530 | if not url.endswith('/'): |
|
500 | if not url.endswith('/'): | |
531 | url += '/' |
|
501 | url += '/' | |
@@ -557,10 +527,3 class hgwebdir(object): | |||||
557 | } |
|
527 | } | |
558 | tmpl = templater.templater.frommapfile(mapfile, defaults=defaults) |
|
528 | tmpl = templater.templater.frommapfile(mapfile, defaults=defaults) | |
559 | return tmpl |
|
529 | return tmpl | |
560 |
|
||||
561 | def updatereqenv(self, env): |
|
|||
562 | if self._baseurl is not None: |
|
|||
563 | name, port, path = geturlcgivars(self._baseurl, env['SERVER_PORT']) |
|
|||
564 | env['SERVER_NAME'] = name |
|
|||
565 | env['SERVER_PORT'] = port |
|
|||
566 | env['SCRIPT_NAME'] = path |
|
@@ -157,7 +157,7 class parsedrequest(object): | |||||
157 | # Request body input stream. |
|
157 | # Request body input stream. | |
158 | bodyfh = attr.ib() |
|
158 | bodyfh = attr.ib() | |
159 |
|
159 | |||
160 | def parserequestfromenv(env, bodyfh, reponame=None): |
|
160 | def parserequestfromenv(env, bodyfh, reponame=None, altbaseurl=None): | |
161 | """Parse URL components from environment variables. |
|
161 | """Parse URL components from environment variables. | |
162 |
|
162 | |||
163 | WSGI defines request attributes via environment variables. This function |
|
163 | WSGI defines request attributes via environment variables. This function | |
@@ -167,8 +167,18 def parserequestfromenv(env, bodyfh, rep | |||||
167 | string are effectively shifted from ``PATH_INFO`` to ``SCRIPT_NAME``. |
|
167 | string are effectively shifted from ``PATH_INFO`` to ``SCRIPT_NAME``. | |
168 | This simulates the world view of a WSGI application that processes |
|
168 | This simulates the world view of a WSGI application that processes | |
169 | requests from the base URL of a repo. |
|
169 | requests from the base URL of a repo. | |
|
170 | ||||
|
171 | If ``altbaseurl`` (typically comes from ``web.baseurl`` config option) | |||
|
172 | is defined, it is used - instead of the WSGI environment variables - for | |||
|
173 | constructing URL components up to and including the WSGI application path. | |||
|
174 | For example, if the current WSGI application is at ``/repo`` and a request | |||
|
175 | is made to ``/rev/@`` with this argument set to | |||
|
176 | ``http://myserver:9000/prefix``, the URL and path components will resolve as | |||
|
177 | if the request were to ``http://myserver:9000/prefix/rev/@``. In other | |||
|
178 | words, ``wsgi.url_scheme``, ``SERVER_NAME``, ``SERVER_PORT``, and | |||
|
179 | ``SCRIPT_NAME`` are all effectively replaced by components from this URL. | |||
170 | """ |
|
180 | """ | |
171 |
# PEP |
|
181 | # PEP 3333 defines the WSGI spec and is a useful reference for this code. | |
172 |
|
182 | |||
173 | # We first validate that the incoming object conforms with the WSGI spec. |
|
183 | # We first validate that the incoming object conforms with the WSGI spec. | |
174 | # We only want to be dealing with spec-conforming WSGI implementations. |
|
184 | # We only want to be dealing with spec-conforming WSGI implementations. | |
@@ -184,20 +194,27 def parserequestfromenv(env, bodyfh, rep | |||||
184 | env = {k: v.encode('latin-1') if isinstance(v, str) else v |
|
194 | env = {k: v.encode('latin-1') if isinstance(v, str) else v | |
185 | for k, v in env.iteritems()} |
|
195 | for k, v in env.iteritems()} | |
186 |
|
196 | |||
|
197 | if altbaseurl: | |||
|
198 | altbaseurl = util.url(altbaseurl) | |||
|
199 | ||||
187 | # https://www.python.org/dev/peps/pep-0333/#environ-variables defines |
|
200 | # https://www.python.org/dev/peps/pep-0333/#environ-variables defines | |
188 | # the environment variables. |
|
201 | # the environment variables. | |
189 | # https://www.python.org/dev/peps/pep-0333/#url-reconstruction defines |
|
202 | # https://www.python.org/dev/peps/pep-0333/#url-reconstruction defines | |
190 | # how URLs are reconstructed. |
|
203 | # how URLs are reconstructed. | |
191 | fullurl = env['wsgi.url_scheme'] + '://' |
|
204 | fullurl = env['wsgi.url_scheme'] + '://' | |
|
205 | ||||
|
206 | if altbaseurl and altbaseurl.scheme: | |||
|
207 | advertisedfullurl = altbaseurl.scheme + '://' | |||
|
208 | else: | |||
192 | advertisedfullurl = fullurl |
|
209 | advertisedfullurl = fullurl | |
193 |
|
210 | |||
194 | def addport(s): |
|
211 | def addport(s, port): | |
195 | if env['wsgi.url_scheme'] == 'https': |
|
212 | if s.startswith('https://'): | |
196 |
if |
|
213 | if port != '443': | |
197 |
s += ':' + |
|
214 | s += ':' + port | |
198 | else: |
|
215 | else: | |
199 |
if |
|
216 | if port != '80': | |
200 |
s += ':' + |
|
217 | s += ':' + port | |
201 |
|
218 | |||
202 | return s |
|
219 | return s | |
203 |
|
220 | |||
@@ -205,17 +222,39 def parserequestfromenv(env, bodyfh, rep | |||||
205 | fullurl += env['HTTP_HOST'] |
|
222 | fullurl += env['HTTP_HOST'] | |
206 | else: |
|
223 | else: | |
207 | fullurl += env['SERVER_NAME'] |
|
224 | fullurl += env['SERVER_NAME'] | |
208 | fullurl = addport(fullurl) |
|
225 | fullurl = addport(fullurl, env['SERVER_PORT']) | |
|
226 | ||||
|
227 | if altbaseurl and altbaseurl.host: | |||
|
228 | advertisedfullurl += altbaseurl.host | |||
209 |
|
229 | |||
|
230 | if altbaseurl.port: | |||
|
231 | port = altbaseurl.port | |||
|
232 | elif altbaseurl.scheme == 'http' and not altbaseurl.port: | |||
|
233 | port = '80' | |||
|
234 | elif altbaseurl.scheme == 'https' and not altbaseurl.port: | |||
|
235 | port = '443' | |||
|
236 | else: | |||
|
237 | port = env['SERVER_PORT'] | |||
|
238 | ||||
|
239 | advertisedfullurl = addport(advertisedfullurl, port) | |||
|
240 | else: | |||
210 | advertisedfullurl += env['SERVER_NAME'] |
|
241 | advertisedfullurl += env['SERVER_NAME'] | |
211 | advertisedfullurl = addport(advertisedfullurl) |
|
242 | advertisedfullurl = addport(advertisedfullurl, env['SERVER_PORT']) | |
212 |
|
243 | |||
213 | baseurl = fullurl |
|
244 | baseurl = fullurl | |
214 | advertisedbaseurl = advertisedfullurl |
|
245 | advertisedbaseurl = advertisedfullurl | |
215 |
|
246 | |||
216 | fullurl += util.urlreq.quote(env.get('SCRIPT_NAME', '')) |
|
247 | fullurl += util.urlreq.quote(env.get('SCRIPT_NAME', '')) | |
|
248 | fullurl += util.urlreq.quote(env.get('PATH_INFO', '')) | |||
|
249 | ||||
|
250 | if altbaseurl: | |||
|
251 | path = altbaseurl.path or '' | |||
|
252 | if path and not path.startswith('/'): | |||
|
253 | path = '/' + path | |||
|
254 | advertisedfullurl += util.urlreq.quote(path) | |||
|
255 | else: | |||
217 | advertisedfullurl += util.urlreq.quote(env.get('SCRIPT_NAME', '')) |
|
256 | advertisedfullurl += util.urlreq.quote(env.get('SCRIPT_NAME', '')) | |
218 | fullurl += util.urlreq.quote(env.get('PATH_INFO', '')) |
|
257 | ||
219 | advertisedfullurl += util.urlreq.quote(env.get('PATH_INFO', '')) |
|
258 | advertisedfullurl += util.urlreq.quote(env.get('PATH_INFO', '')) | |
220 |
|
259 | |||
221 | if env.get('QUERY_STRING'): |
|
260 | if env.get('QUERY_STRING'): | |
@@ -226,6 +265,11 def parserequestfromenv(env, bodyfh, rep | |||||
226 | # that represents the repository being dispatched to. When computing |
|
265 | # that represents the repository being dispatched to. When computing | |
227 | # the dispatch info, we ignore these leading path components. |
|
266 | # the dispatch info, we ignore these leading path components. | |
228 |
|
267 | |||
|
268 | if altbaseurl: | |||
|
269 | apppath = altbaseurl.path or '' | |||
|
270 | if apppath and not apppath.startswith('/'): | |||
|
271 | apppath = '/' + apppath | |||
|
272 | else: | |||
229 | apppath = env.get('SCRIPT_NAME', '') |
|
273 | apppath = env.get('SCRIPT_NAME', '') | |
230 |
|
274 | |||
231 | if reponame: |
|
275 | if reponame: | |
@@ -545,7 +589,7 class wsgirequest(object): | |||||
545 | instantiate instances of this class, which provides higher-level APIs |
|
589 | instantiate instances of this class, which provides higher-level APIs | |
546 | for obtaining request parameters, writing HTTP output, etc. |
|
590 | for obtaining request parameters, writing HTTP output, etc. | |
547 | """ |
|
591 | """ | |
548 | def __init__(self, wsgienv, start_response): |
|
592 | def __init__(self, wsgienv, start_response, altbaseurl=None): | |
549 | version = wsgienv[r'wsgi.version'] |
|
593 | version = wsgienv[r'wsgi.version'] | |
550 | if (version < (1, 0)) or (version >= (2, 0)): |
|
594 | if (version < (1, 0)) or (version >= (2, 0)): | |
551 | raise RuntimeError("Unknown and unsupported WSGI version %d.%d" |
|
595 | raise RuntimeError("Unknown and unsupported WSGI version %d.%d" | |
@@ -563,7 +607,7 class wsgirequest(object): | |||||
563 | self.multiprocess = wsgienv[r'wsgi.multiprocess'] |
|
607 | self.multiprocess = wsgienv[r'wsgi.multiprocess'] | |
564 | self.run_once = wsgienv[r'wsgi.run_once'] |
|
608 | self.run_once = wsgienv[r'wsgi.run_once'] | |
565 | self.env = wsgienv |
|
609 | self.env = wsgienv | |
566 | self.req = parserequestfromenv(wsgienv, inp) |
|
610 | self.req = parserequestfromenv(wsgienv, inp, altbaseurl=altbaseurl) | |
567 | self.res = wsgiresponse(self.req, start_response) |
|
611 | self.res = wsgiresponse(self.req, start_response) | |
568 | self._start_response = start_response |
|
612 | self._start_response = start_response | |
569 | self.server_write = None |
|
613 | self.server_write = None |
@@ -23,11 +23,12 DEFAULT_ENV = { | |||||
23 | r'wsgi.run_once': False, |
|
23 | r'wsgi.run_once': False, | |
24 | } |
|
24 | } | |
25 |
|
25 | |||
26 | def parse(env, bodyfh=None, reponame=None, extra=None): |
|
26 | def parse(env, bodyfh=None, reponame=None, altbaseurl=None, extra=None): | |
27 | env = dict(env) |
|
27 | env = dict(env) | |
28 | env.update(extra or {}) |
|
28 | env.update(extra or {}) | |
29 |
|
29 | |||
30 |
return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame |
|
30 | return requestmod.parserequestfromenv(env, bodyfh, reponame=reponame, | |
|
31 | altbaseurl=altbaseurl) | |||
31 |
|
32 | |||
32 | class ParseRequestTests(unittest.TestCase): |
|
33 | class ParseRequestTests(unittest.TestCase): | |
33 | def testdefault(self): |
|
34 | def testdefault(self): | |
@@ -242,6 +243,174 class ParseRequestTests(unittest.TestCas | |||||
242 | self.assertEqual(r.dispatchpath, b'path1/path2') |
|
243 | self.assertEqual(r.dispatchpath, b'path1/path2') | |
243 | self.assertEqual(r.reponame, b'prefix/repo') |
|
244 | self.assertEqual(r.reponame, b'prefix/repo') | |
244 |
|
245 | |||
|
246 | def testaltbaseurl(self): | |||
|
247 | # Simple hostname remap. | |||
|
248 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver') | |||
|
249 | ||||
|
250 | self.assertEqual(r.url, b'http://testserver') | |||
|
251 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
252 | self.assertEqual(r.advertisedurl, b'http://altserver') | |||
|
253 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
254 | self.assertEqual(r.urlscheme, b'http') | |||
|
255 | self.assertEqual(r.apppath, b'') | |||
|
256 | self.assertEqual(r.dispatchparts, []) | |||
|
257 | self.assertIsNone(r.dispatchpath) | |||
|
258 | self.assertIsNone(r.reponame) | |||
|
259 | ||||
|
260 | # With a custom port. | |||
|
261 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver:8000') | |||
|
262 | self.assertEqual(r.url, b'http://testserver') | |||
|
263 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
264 | self.assertEqual(r.advertisedurl, b'http://altserver:8000') | |||
|
265 | self.assertEqual(r.advertisedbaseurl, b'http://altserver:8000') | |||
|
266 | self.assertEqual(r.urlscheme, b'http') | |||
|
267 | self.assertEqual(r.apppath, b'') | |||
|
268 | self.assertEqual(r.dispatchparts, []) | |||
|
269 | self.assertIsNone(r.dispatchpath) | |||
|
270 | self.assertIsNone(r.reponame) | |||
|
271 | ||||
|
272 | # With a changed protocol. | |||
|
273 | r = parse(DEFAULT_ENV, altbaseurl='https://altserver') | |||
|
274 | self.assertEqual(r.url, b'http://testserver') | |||
|
275 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
276 | self.assertEqual(r.advertisedurl, b'https://altserver') | |||
|
277 | self.assertEqual(r.advertisedbaseurl, b'https://altserver') | |||
|
278 | # URL scheme is defined as the actual scheme, not advertised. | |||
|
279 | self.assertEqual(r.urlscheme, b'http') | |||
|
280 | self.assertEqual(r.apppath, b'') | |||
|
281 | self.assertEqual(r.dispatchparts, []) | |||
|
282 | self.assertIsNone(r.dispatchpath) | |||
|
283 | self.assertIsNone(r.reponame) | |||
|
284 | ||||
|
285 | # Need to specify explicit port number for proper https:// alt URLs. | |||
|
286 | r = parse(DEFAULT_ENV, altbaseurl='https://altserver:443') | |||
|
287 | self.assertEqual(r.url, b'http://testserver') | |||
|
288 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
289 | self.assertEqual(r.advertisedurl, b'https://altserver') | |||
|
290 | self.assertEqual(r.advertisedbaseurl, b'https://altserver') | |||
|
291 | self.assertEqual(r.urlscheme, b'http') | |||
|
292 | self.assertEqual(r.apppath, b'') | |||
|
293 | self.assertEqual(r.dispatchparts, []) | |||
|
294 | self.assertIsNone(r.dispatchpath) | |||
|
295 | self.assertIsNone(r.reponame) | |||
|
296 | ||||
|
297 | # With only PATH_INFO defined. | |||
|
298 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver', extra={ | |||
|
299 | r'PATH_INFO': r'/path1/path2', | |||
|
300 | }) | |||
|
301 | self.assertEqual(r.url, b'http://testserver/path1/path2') | |||
|
302 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
303 | self.assertEqual(r.advertisedurl, b'http://altserver/path1/path2') | |||
|
304 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
305 | self.assertEqual(r.urlscheme, b'http') | |||
|
306 | self.assertEqual(r.apppath, b'') | |||
|
307 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
308 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
309 | self.assertIsNone(r.reponame) | |||
|
310 | ||||
|
311 | # Path on alt URL. | |||
|
312 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altpath') | |||
|
313 | self.assertEqual(r.url, b'http://testserver') | |||
|
314 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
315 | self.assertEqual(r.advertisedurl, b'http://altserver/altpath') | |||
|
316 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
317 | self.assertEqual(r.urlscheme, b'http') | |||
|
318 | self.assertEqual(r.apppath, b'/altpath') | |||
|
319 | self.assertEqual(r.dispatchparts, []) | |||
|
320 | self.assertIsNone(r.dispatchpath) | |||
|
321 | self.assertIsNone(r.reponame) | |||
|
322 | ||||
|
323 | # With a trailing slash. | |||
|
324 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altpath/') | |||
|
325 | self.assertEqual(r.url, b'http://testserver') | |||
|
326 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
327 | self.assertEqual(r.advertisedurl, b'http://altserver/altpath/') | |||
|
328 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
329 | self.assertEqual(r.urlscheme, b'http') | |||
|
330 | self.assertEqual(r.apppath, b'/altpath/') | |||
|
331 | self.assertEqual(r.dispatchparts, []) | |||
|
332 | self.assertIsNone(r.dispatchpath) | |||
|
333 | self.assertIsNone(r.reponame) | |||
|
334 | ||||
|
335 | # PATH_INFO + path on alt URL. | |||
|
336 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altpath', extra={ | |||
|
337 | r'PATH_INFO': r'/path1/path2', | |||
|
338 | }) | |||
|
339 | self.assertEqual(r.url, b'http://testserver/path1/path2') | |||
|
340 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
341 | self.assertEqual(r.advertisedurl, | |||
|
342 | b'http://altserver/altpath/path1/path2') | |||
|
343 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
344 | self.assertEqual(r.urlscheme, b'http') | |||
|
345 | self.assertEqual(r.apppath, b'/altpath') | |||
|
346 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
347 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
348 | self.assertIsNone(r.reponame) | |||
|
349 | ||||
|
350 | # PATH_INFO + path on alt URL with trailing slash. | |||
|
351 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altpath/', extra={ | |||
|
352 | r'PATH_INFO': r'/path1/path2', | |||
|
353 | }) | |||
|
354 | self.assertEqual(r.url, b'http://testserver/path1/path2') | |||
|
355 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
356 | self.assertEqual(r.advertisedurl, | |||
|
357 | b'http://altserver/altpath//path1/path2') | |||
|
358 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
359 | self.assertEqual(r.urlscheme, b'http') | |||
|
360 | self.assertEqual(r.apppath, b'/altpath/') | |||
|
361 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
362 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
363 | self.assertIsNone(r.reponame) | |||
|
364 | ||||
|
365 | # Local SCRIPT_NAME is ignored. | |||
|
366 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver', extra={ | |||
|
367 | r'SCRIPT_NAME': r'/script', | |||
|
368 | r'PATH_INFO': r'/path1/path2', | |||
|
369 | }) | |||
|
370 | self.assertEqual(r.url, b'http://testserver/script/path1/path2') | |||
|
371 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
372 | self.assertEqual(r.advertisedurl, b'http://altserver/path1/path2') | |||
|
373 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
374 | self.assertEqual(r.urlscheme, b'http') | |||
|
375 | self.assertEqual(r.apppath, b'') | |||
|
376 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
377 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
378 | self.assertIsNone(r.reponame) | |||
|
379 | ||||
|
380 | # Use remote's path for script name, app path | |||
|
381 | r = parse(DEFAULT_ENV, altbaseurl='http://altserver/altroot', extra={ | |||
|
382 | r'SCRIPT_NAME': r'/script', | |||
|
383 | r'PATH_INFO': r'/path1/path2', | |||
|
384 | }) | |||
|
385 | self.assertEqual(r.url, b'http://testserver/script/path1/path2') | |||
|
386 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
387 | self.assertEqual(r.advertisedurl, | |||
|
388 | b'http://altserver/altroot/path1/path2') | |||
|
389 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
390 | self.assertEqual(r.urlscheme, b'http') | |||
|
391 | self.assertEqual(r.apppath, b'/altroot') | |||
|
392 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
393 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
394 | self.assertIsNone(r.reponame) | |||
|
395 | ||||
|
396 | # reponame is factored in properly. | |||
|
397 | r = parse(DEFAULT_ENV, reponame=b'repo', | |||
|
398 | altbaseurl='http://altserver/altroot', | |||
|
399 | extra={ | |||
|
400 | r'SCRIPT_NAME': r'/script', | |||
|
401 | r'PATH_INFO': r'/repo/path1/path2', | |||
|
402 | }) | |||
|
403 | ||||
|
404 | self.assertEqual(r.url, b'http://testserver/script/repo/path1/path2') | |||
|
405 | self.assertEqual(r.baseurl, b'http://testserver') | |||
|
406 | self.assertEqual(r.advertisedurl, | |||
|
407 | b'http://altserver/altroot/repo/path1/path2') | |||
|
408 | self.assertEqual(r.advertisedbaseurl, b'http://altserver') | |||
|
409 | self.assertEqual(r.apppath, b'/altroot/repo') | |||
|
410 | self.assertEqual(r.dispatchparts, [b'path1', b'path2']) | |||
|
411 | self.assertEqual(r.dispatchpath, b'path1/path2') | |||
|
412 | self.assertEqual(r.reponame, b'repo') | |||
|
413 | ||||
245 | if __name__ == '__main__': |
|
414 | if __name__ == '__main__': | |
246 | import silenttestrunner |
|
415 | import silenttestrunner | |
247 | silenttestrunner.main(__name__) |
|
416 | silenttestrunner.main(__name__) |
General Comments 0
You need to be logged in to leave comments.
Login now