From b64268655a5cb17d31ad2c95b3d6a962d881f77a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 21 Apr 2011 20:48:46 -0400 Subject: share call_app_with_subpath_as_path_info between static view and wsgiapp2 --- pyramid/request.py | 69 ++++++++++++++++++++++----------------- pyramid/static.py | 7 ++-- pyramid/tests/test_integration.py | 4 +-- pyramid/tests/test_static.py | 5 +-- pyramid/tests/test_wsgi.py | 43 ++++++++---------------- pyramid/wsgi.py | 5 ++- 6 files changed, 61 insertions(+), 72 deletions(-) diff --git a/pyramid/request.py b/pyramid/request.py index 1aceccdba..e53a70023 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -394,10 +394,11 @@ def add_global_response_headers(request, headerlist): response.headerlist.append((k, v)) request.add_response_callback(add_headers) -def subpath_as_path_info(request, default_script_name='',default_path_info='/'): - # Copy the request. Use the request's subpath (if it exists) as the new - # request's PATH_INFO. Set the request copy's SCRIPT_NAME to the prefix - # before the subpath. +def call_app_subpath_as_path_info(request, app): + # Copy the request. Use the source request's subpath (if it exists) as + # the new request's PATH_INFO. Set the request copy's SCRIPT_NAME to the + # prefix before the subpath. Call the application with the new request + # and return a response. # # Postconditions: # - SCRIPT_NAME and PATH_INFO are empty or start with / @@ -408,32 +409,40 @@ def subpath_as_path_info(request, default_script_name='',default_path_info='/'): script_name = request.environ.get('SCRIPT_NAME', '') path_info = request.environ.get('PATH_INFO', '/') - new_script_name = default_script_name - new_path_info = default_path_info + new_script_name = '' subpath = list(getattr(request, 'subpath', ())) - if subpath: - # compute new_path_info - new_path_info = '/' + '/'.join([quote_path_segment(x) for x in subpath]) - if path_info.endswith('/'): - # readd trailing slash stripped by subpath (traversal) - # conversion - new_path_info += '/' - - # compute new_script_name - tmp = [] - workback = (script_name + path_info).split('/') - while workback: - el = workback.pop() - if el: - tmp.insert(0, el.decode('utf-8')) - if tmp == subpath: - new_script_name = '/'.join(workback) - break - - request = request.copy() - request.environ['SCRIPT_NAME'] = new_script_name - request.environ['PATH_INFO'] = new_path_info - - return request + # compute new_path_info + new_path_info = '/' + '/'.join([quote_path_segment(x) for x in subpath]) + + if new_path_info != '/': + if path_info != '/': + if path_info.endswith('/'): + # readd trailing slash stripped by subpath (traversal) + # conversion + new_path_info += '/' + + # compute new_script_name + tmp = [] + workback = (script_name + path_info).split('/') + + # strip trailing slash from workback to avoid appending undue slash + # to script_name + if workback and (workback[-1] == ''): + workback = workback[:-1] + + while workback: + if tmp == subpath: + break + el = workback.pop() + if el: + tmp.insert(0, el.decode('utf-8')) + + new_script_name = '/'.join(workback) + + request_copy = request.copy() + request_copy.environ['SCRIPT_NAME'] = new_script_name + request_copy.environ['PATH_INFO'] = new_path_info + + return request_copy.get_response(app) diff --git a/pyramid/static.py b/pyramid/static.py index c80952129..22e6e9256 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -13,7 +13,7 @@ from zope.interface import implements from pyramid.asset import resolve_asset_spec from pyramid.interfaces import IStaticURLInfo from pyramid.path import caller_package -from pyramid.request import subpath_as_path_info +from pyramid.request import call_app_subpath_as_path_info from pyramid.url import route_url class PackageURLParser(StaticURLParser): @@ -209,7 +209,4 @@ class static_view(object): self.app = app def __call__(self, context, request): - script_name = request.environ.get('SCRIPT_NAME', '') - path_info = request.environ.get('PATH_INFO', '/') - request_copy = subpath_as_path_info(request, script_name, path_info) - return request_copy.get_response(self.app) + return call_app_subpath_as_path_info(request, self.app) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 1f9484279..e3a1a8003 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -104,7 +104,7 @@ class TestStaticApp(unittest.TestCase): from webob import Request context = DummyContext() from StringIO import StringIO - request = Request({'PATH_INFO':'', + request = Request({'PATH_INFO':'/static', 'SCRIPT_NAME':'/script_name', 'SERVER_NAME':'localhost', 'SERVER_PORT':'80', @@ -112,7 +112,7 @@ class TestStaticApp(unittest.TestCase): 'wsgi.version':(1,0), 'wsgi.url_scheme':'http', 'wsgi.input':StringIO()}) - request.subpath = ['static'] + request.subpath = ('static',) result = staticapp(context, request) self.assertEqual(result.status, '301 Moved Permanently') self.assertEqual(result.location, diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py index b9d464bf1..0095b29d3 100644 --- a/pyramid/tests/test_static.py +++ b/pyramid/tests/test_static.py @@ -268,8 +268,9 @@ class Test_static_view(unittest.TestCase): SCRIPT_NAME='/script_name') view(context, request) self.assertEqual(request.copied, True) - self.assertEqual(request.environ['PATH_INFO'], '/path_info') - self.assertEqual(request.environ['SCRIPT_NAME'], '/script_name') + self.assertEqual(request.environ['PATH_INFO'], '/') + self.assertEqual(request.environ['SCRIPT_NAME'], + '/script_name/path_info') def test_with_subpath_path_info_ends_with_slash(self): view = self._makeOne('fixtures', package_name='another') diff --git a/pyramid/tests/test_wsgi.py b/pyramid/tests/test_wsgi.py index 067c86127..06bcf1cb2 100644 --- a/pyramid/tests/test_wsgi.py +++ b/pyramid/tests/test_wsgi.py @@ -20,11 +20,9 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_with_subpath_and_view_name(self): context = DummyContext() request = DummyRequest() - request.traversed = ['a', 'b'] - request.virtual_root_path = ['a'] - request.subpath = ['subpath'] - request.view_name = 'view_name' - request.environ = {'SCRIPT_NAME':'/foo'} + request.subpath = ('subpath',) + request.environ = {'SCRIPT_NAME':'/foo', + 'PATH_INFO':'/b/view_name/subpath'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -34,11 +32,8 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_with_subpath_no_view_name(self): context = DummyContext() request = DummyRequest() - request.traversed = ['a', 'b'] - request.virtual_root_path = ['a'] - request.subpath = ['subpath'] - request.view_name = '' - request.environ = {'SCRIPT_NAME':'/foo'} + request.subpath = ('subpath',) + request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/subpath'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -48,11 +43,8 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_no_subpath_with_view_name(self): context = DummyContext() request = DummyRequest() - request.traversed = ['a', 'b'] - request.virtual_root_path = ['a'] - request.subpath = [] - request.view_name = 'view_name' - request.environ = {'SCRIPT_NAME':'/foo'} + request.subpath = () + request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/view_name'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -62,11 +54,8 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_traversed_empty_with_view_name(self): context = DummyContext() request = DummyRequest() - request.traversed = [] - request.virtual_root_path = [] - request.subpath = [] - request.view_name = 'view_name' - request.environ = {'SCRIPT_NAME':'/foo'} + request.subpath = () + request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/view_name'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -76,11 +65,8 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_traversed_empty_no_view_name(self): context = DummyContext() request = DummyRequest() - request.traversed = [] - request.virtual_root_path = [] - request.subpath = [] - request.view_name = '' - request.environ = {'SCRIPT_NAME':'/foo'} + request.subpath = () + request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) @@ -90,11 +76,8 @@ class WSGIApp2Tests(unittest.TestCase): def test_decorator_traversed_empty_no_view_name_no_script_name(self): context = DummyContext() request = DummyRequest() - request.traversed = [] - request.virtual_root_path = [] - request.subpath = [] - request.view_name = '' - request.environ = {'SCRIPT_NAME':''} + request.subpath = () + request.environ = {'SCRIPT_NAME':'', 'PATH_INFO':'/'} decorator = self._callFUT(dummyapp) response = decorator(context, request) self.assertEqual(response, dummyapp) diff --git a/pyramid/wsgi.py b/pyramid/wsgi.py index ef8863cfa..71045bb54 100644 --- a/pyramid/wsgi.py +++ b/pyramid/wsgi.py @@ -1,5 +1,5 @@ from pyramid.compat import wraps -from pyramid.request import subpath_as_path_info +from pyramid.request import call_app_subpath_as_path_info def wsgiapp(wrapped): """ Decorator to turn a WSGI application into a :app:`Pyramid` @@ -62,7 +62,6 @@ def wsgiapp2(wrapped): up before the application is invoked. """ def decorator(context, request): - request_copy = subpath_as_path_info(request) - return request_copy.get_response(wrapped) + return call_app_subpath_as_path_info(request, wrapped) return wraps(wrapped)(decorator) -- cgit v1.2.3