From b14f4aa1682b77681a760ed948f8972a4e0d7d2a Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 25 Jun 2015 13:57:47 -0400 Subject: [PATCH] Fix a bug in extension-based content-type guessing with a trailing slash. Change-Id: I9b7e96ea1541af8b8964b95befa814297f404cd1 --- pecan/core.py | 6 ++-- pecan/tests/test_base.py | 61 ++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/pecan/core.py b/pecan/core.py index 4684b5f..9514638 100644 --- a/pecan/core.py +++ b/pecan/core.py @@ -445,13 +445,13 @@ class PecanBase(object): if self.guess_content_type_from_ext \ and not pecan_state['content_type'] \ and '.' in path: - new_path, extension = splitext(path) + _, extension = splitext(path.rstrip('/')) # preface with a letter to ensure compat for 2.5 potential_type = guess_type('x' + extension)[0] - if potential_type is not None: - path = new_path + if extension and potential_type is not None: + path = ''.join(path.rsplit(extension, 1)) pecan_state['extension'] = extension pecan_state['content_type'] = potential_type diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py index 8558f82..5d4eb76 100644 --- a/pecan/tests/test_base.py +++ b/pecan/tests/test_base.py @@ -1401,24 +1401,28 @@ class TestFileTypeExtensions(PecanTestCase): return TestApp(Pecan(RootController())) def test_html_extension(self): - r = self.app_.get('/index.html') - assert r.status_int == 200 - assert r.body == b_('.html') + for path in ('/index.html', '/index.html/'): + r = self.app_.get(path) + assert r.status_int == 200 + assert r.body == b_('.html') def test_image_extension(self): - r = self.app_.get('/image.png') - assert r.status_int == 200 - assert r.body == b_('.png') + for path in ('/index.png', '/index.png/'): + r = self.app_.get(path) + assert r.status_int == 200 + assert r.body == b_('.png') def test_hidden_file(self): - r = self.app_.get('/.vimrc') - assert r.status_int == 204 - assert r.body == b_('') + for path in ('/.vimrc', '/.vimrc/'): + r = self.app_.get(path) + assert r.status_int == 204 + assert r.body == b_('') def test_multi_dot_extension(self): - r = self.app_.get('/gradient.min.js') - assert r.status_int == 200 - assert r.body == b_('.js') + for path in ('/gradient.min.js', '/gradient.min.js/'): + r = self.app_.get(path) + assert r.status_int == 200 + assert r.body == b_('.js') def test_bad_content_type(self): class RootController(object): @@ -1469,6 +1473,39 @@ class TestFileTypeExtensions(PecanTestCase): assert r.status_int == 200 assert r.body == b_('SOME VALUE') + def test_content_type_guessing_disabled(self): + + class ResourceController(object): + + def __init__(self, name): + self.name = name + assert self.name == 'file.html' + + @expose('json') + def index(self): + return dict(name=self.name) + + class RootController(object): + + @expose() + def _lookup(self, name, *remainder): + return ResourceController(name), remainder + + app = TestApp( + Pecan(RootController(), guess_content_type_from_ext=False) + ) + + r = app.get('/file.html/') + assert r.status_int == 200 + result = dict(json.loads(r.body.decode())) + assert result == {'name': 'file.html'} + + r = app.get('/file.html') + assert r.status_int == 302 + r = r.follow() + result = dict(json.loads(r.body.decode())) + assert result == {'name': 'file.html'} + class TestContentTypeByAcceptHeaders(PecanTestCase):