Mercurial > piecrust2
changeset 568:6b6c5442c790
bug: Correctly handle root URLs with special characters.
The `site/root` setting is now pre-escaped to get a correct URL, and routing
excludes it from escaping.
Add unit tests.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 13 Oct 2015 22:50:38 -0700 |
parents | a65f04ddbea2 |
children | 34e57d4b97e2 |
files | piecrust/app.py piecrust/routing.py tests/bakes/test_special_root.yaml tests/test_baking_baker.py tests/test_routing.py |
diffstat | 5 files changed, 57 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/app.py Tue Oct 13 22:46:05 2015 -0700 +++ b/piecrust/app.py Tue Oct 13 22:50:38 2015 -0700 @@ -2,6 +2,7 @@ import json import time import os.path +import urllib.parse import codecs import hashlib import logging @@ -145,7 +146,7 @@ if not sitec['root'].startswith('/'): raise ConfigurationError("The `site/root` setting must start " "with a slash.") - sitec['root'] = sitec['root'].rstrip('/') + '/' + sitec['root'] = urllib.parse.quote(sitec['root'].rstrip('/') + '/') # Cache auto-format regexes. if not isinstance(sitec['auto_formats'], dict):
--- a/piecrust/routing.py Tue Oct 13 22:46:05 2015 -0700 +++ b/piecrust/routing.py Tue Oct 13 22:50:38 2015 -0700 @@ -227,7 +227,7 @@ else: uri = base_uri + ext - uri = urllib.parse.quote(self.uri_root + uri) + uri = self.uri_root + urllib.parse.quote(uri) if self.show_debug_info: uri += '?!debug'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/bakes/test_special_root.yaml Tue Oct 13 22:50:38 2015 -0700 @@ -0,0 +1,10 @@ +--- +config: + site: + root: /~john/public/ +in: + pages/about.md: 'URL: {{page.url}}, LINK: {{pcurl("missing")}}' + pages/_index.md: 'URL: {{page.url}}' +out: + about.html: 'URL: /%7Ejohn/public/about.html, LINK: /%7Ejohn/public/missing.html' + index.html: 'URL: /%7Ejohn/public/'
--- a/tests/test_baking_baker.py Tue Oct 13 22:46:05 2015 -0700 +++ b/tests/test_baking_baker.py Tue Oct 13 22:50:38 2015 -0700 @@ -1,5 +1,6 @@ import time import os.path +import urllib.parse import pytest from piecrust.baking.baker import Baker from piecrust.baking.single import PageBaker @@ -41,8 +42,8 @@ app.config.set('site/pretty_urls', True) assert app.config.get('site/pretty_urls') == pretty - for site_root in ['/', '/whatever/']: - app.config.set('site/root', site_root) + for site_root in ['/', '/whatever/', '/~johndoe/']: + app.config.set('site/root', urllib.parse.quote(site_root)) baker = PageBaker(app, '/destination') path = baker.getOutputPath(site_root + uri) expected = os.path.normpath(
--- a/tests/test_routing.py Tue Oct 13 22:46:05 2015 -0700 +++ b/tests/test_routing.py Tue Oct 13 22:50:38 2015 -0700 @@ -1,3 +1,4 @@ +import urllib.parse import pytest from piecrust.routing import Route from .mockutil import get_mock_app @@ -34,7 +35,11 @@ ('/something', '/%foo%', set(['foo'])), ('/something', '/%path:foo%', set(['foo'])), ('/something', '/%foo%/%bar%', set(['foo', 'bar'])), - ('/something', '/%foo%/%path:bar%', set(['foo', 'bar'])) + ('/something', '/%foo%/%path:bar%', set(['foo', 'bar'])), + ('/~johndoe', '/%foo%', set(['foo'])), + ('/~johndoe', '/%path:foo%', set(['foo'])), + ('/~johndoe', '/%foo%/%bar%', set(['foo', 'bar'])), + ('/~johndoe', '/%foo%/%path:bar%', set(['foo', 'bar'])) ]) def test_required_metadata(site_root, route_pattern, expected_required_metadata): @@ -91,22 +96,44 @@ ('/blah', {'url': '/prefix/%path:foo%'}, 'prefix', {'foo': ''}), + + ('/~johndoe', {'url': '/%foo%'}, + 'something', + {'foo': 'something'}), + ('/~johndoe', {'url': '/%foo%'}, + 'something/other', + None), + ('/~johndoe', {'url': '/%path:foo%'}, + 'something/other', + {'foo': 'something/other'}), + ('/~johndoe', {'url': '/%path:foo%'}, + '', + {'foo': ''}), + ('/~johndoe', {'url': '/prefix/%path:foo%'}, + 'prefix/something/other', + {'foo': 'something/other'}), + ('/~johndoe', {'url': '/prefix/%path:foo%'}, + 'prefix/', + {'foo': ''}), + ('/~johndoe', {'url': '/prefix/%path:foo%'}, + 'prefix', + {'foo': ''}), ]) def test_match_uri(site_root, config, uri, expected_match): site_root = site_root.rstrip('/') + '/' app = get_mock_app() - app.config.set('site/root', site_root) + app.config.set('site/root', urllib.parse.quote(site_root)) config.setdefault('source', 'blah') route = Route(app, config) assert route.uri_pattern == config['url'].lstrip('/') - m = route.matchUri(site_root + uri) + m = route.matchUri(urllib.parse.quote(site_root) + uri) assert m == expected_match @pytest.mark.parametrize( 'site_root', [ - ('/'), ('/whatever') + ('/'), ('/whatever'), ('/~johndoe') ]) def test_match_uri_requires_absolute_uri(site_root): with pytest.raises(Exception): @@ -148,14 +175,15 @@ ('foo.bar.ext', 2, False, 'foo.bar/2.ext') ]) def test_get_uri(slug, page_num, pretty, expected): - app = get_mock_app() - app.config.set('site/root', '/blah/') - app.config.set('site/pretty_urls', pretty) - app.config.set('site/trailing_slash', False) - app.config.set('__cache/pagination_suffix_format', '/%(num)d') + for root in ['/', '/blah/', '/~johndoe/']: + app = get_mock_app() + app.config.set('site/root', urllib.parse.quote(root)) + app.config.set('site/pretty_urls', pretty) + app.config.set('site/trailing_slash', False) + app.config.set('__cache/pagination_suffix_format', '/%(num)d') - config = {'url': '/%path:slug%', 'source': 'blah'} - route = Route(app, config) - uri = route.getUri({'slug': slug}, sub_num=page_num) - assert uri == ('/blah/' + expected) + config = {'url': '/%path:slug%', 'source': 'blah'} + route = Route(app, config) + uri = route.getUri({'slug': slug}, sub_num=page_num) + assert uri == (urllib.parse.quote(root) + expected)