diff --git a/src/milla/__init__.py b/src/milla/__init__.py index 29eb958..bef31c3 100644 --- a/src/milla/__init__.py +++ b/src/milla/__init__.py @@ -61,25 +61,44 @@ class Request(webob.Request): req.config = {} return req - def relative_url(self, other_url, to_application=True, path_only=True, - **vars): #@ReservedAssignment - '''Create a new URL relative to the request URL + def create_href(self, path, **keywords): + '''Combine the application's path with a path to form an HREF - :param other_url: relative path to join with the request URL - :param to_application: If true, generated URL will be relative - to the application's root path, otherwise relative to the - server root - :param path_only: If true, scheme and host will be omitted + :param path: relative path to join with the request URL Any other keyword arguments will be encoded and appended to the URL as querystring arguments. + + The HREF returned will will be the absolute path on the same host + and protocol as the request. To get the full URL including scheme + and host information, use :py:meth:`create_href_full` instead. ''' - url = super(Request, self).relative_url(other_url, to_application) - if path_only: - url = urlparse.urlsplit(url).path - if vars: - url += '?' + urllib.urlencode(vars) + url = self._merge_url(self.script_name, path) + + if keywords: + url += '?' + urllib.urlencode(keywords) + + return url + + def create_href_full(self, path, **keywords): + '''Combine the application's full URL with a path to form a new URL + + :param path: relative path to join with the request URL + + Any other keyword arguments will be encoded and appended to the + URL as querystring arguments/ + + The HREF returned will be the full URL, including scheme and host + information. To get the path only, use :py:meth:`create_href` + instead. + ''' + + url = self._merge_url(self.application_url, path) + + if keywords: + url += '?' + urllib.urlencode(keywords) + return url def static_resource(self, path): @@ -114,6 +133,9 @@ class Request(webob.Request): except KeyError: return path + return self._merge_url(root, path) + + def _merge_url(self, root, path): if path.startswith('/'): path = path[1:] if not root.endswith('/'): diff --git a/src/milla/dispatch/routing.py b/src/milla/dispatch/routing.py index 34ddfde..d16d1fa 100644 --- a/src/milla/dispatch/routing.py +++ b/src/milla/dispatch/routing.py @@ -223,7 +223,7 @@ class Generator(object): url = Generator(request).generate .. deprecated:: 0.2 - Use :py:meth:`milla.Request.relative_url` instead. + Use :py:meth:`milla.Request.create_href` instead. ''' def __init__(self, request, path_only=True): @@ -231,7 +231,7 @@ class Generator(object): self.path_only = path_only warnings.warn( 'Use of Generator is deprecated; ' - 'use milla.Request.relative_url instead', + 'use milla.Request.create_href instead', DeprecationWarning, stacklevel=2 ) @@ -241,10 +241,8 @@ class Generator(object): ''' path = '/'.join(str(s) for s in segments) - while path.startswith('/'): - path = path[1:] - return self.request.relative_url(path, - to_application=True, - path_only=self.path_only, - **vars) + if self.path_only: + return self.request.create_href(path, **vars) + else: + return self.request.create_href_full(path, **vars) diff --git a/src/milla/tests/test_app.py b/src/milla/tests/test_app.py index 7afefa0..3e7dfda 100644 --- a/src/milla/tests/test_app.py +++ b/src/milla/tests/test_app.py @@ -403,3 +403,57 @@ def test_allow_decorator(): return 'success' assert controller.allowed_methods == ('GET', 'HEAD', 'POST') + +def test_create_href_simple(): + '''Request.create_href creates a valid URL path from the application root''' + + environ = environ_for_testing() + request = milla.Request(environ) + url = request.create_href('/bar') + assert url == '/bar', url + +def test_create_href_nonroot(): + '''Request.create_href handles applications mounted somewhere besides /''' + + environ = environ_for_testing() + environ.update({ + 'SCRIPT_NAME': '/test' + }) + request = milla.Request(environ) + url = request.create_href('/bar') + assert url == '/test/bar', url + +def test_create_href_full(): + '''Request.create_href_full creates appropriate full URL''' + + environ = environ_for_testing() + request = milla.Request(environ) + url = request.create_href_full('/bar') + assert url == 'http://127.0.0.1/bar', url + +def test_create_href_full_nonroot(): + '''Request.create_href_full creates correct full URL for nonroot applications''' + + environ = environ_for_testing() + environ.update({ + 'SCRIPT_NAME': '/test' + }) + request = milla.Request(environ) + url = request.create_href_full('/bar') + assert url == 'http://127.0.0.1/test/bar', url + +def test_create_href_keywords(): + '''Request.create_href properly appends querystring arguments''' + + environ = environ_for_testing() + request = milla.Request(environ) + url = request.create_href('/bar', foo='baz') + assert url == '/bar?foo=baz' + +def test_create_href_full_keywords(): + '''Request.create_href_full properly appends querystring arguments''' + + environ = environ_for_testing() + request = milla.Request(environ) + url = request.create_href_full('/bar', foo='baz') + assert url == 'http://127.0.0.1/bar?foo=baz'