From 9ff5ca37815334fdfb1289f9be780a1e25b45996 Mon Sep 17 00:00:00 2001 From: Dave Shawley Date: Sat, 2 Oct 2021 11:44:57 -0400 Subject: [PATCH] Fail gracefully when transcoder is missing. If there is no transcoder for the default content type, sending a response would fail with a "500 Internal Server Error" due to an *unhandled* KeyError. This commit catches the KeyError and produces an explicit "500 Internal Server Error" with an appropriate error message being logged. --- docs/history.rst | 1 + sprockets/mixins/mediatype/content.py | 20 ++++++++++++++------ tests.py | 9 +++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/history.rst b/docs/history.rst index ca0cf03..818ea42 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -7,6 +7,7 @@ Version History - Return a "406 Not Acceptable" if the :http:header:`Accept` header values cannot be matched and there is no default content type configured - Deprecate not having a default content type configured +- Fail gracefully when a transcoder does not exist for the default content type :compare:`3.0.4 <3.0.3...3.0.4>` (2 Nov 2020) --------------------------------------------- diff --git a/sprockets/mixins/mediatype/content.py b/sprockets/mixins/mediatype/content.py index 2fe6abb..2ba01a1 100644 --- a/sprockets/mixins/mediatype/content.py +++ b/sprockets/mixins/mediatype/content.py @@ -414,9 +414,17 @@ class ContentMixin(web.RequestHandler): self._logger.error('please set a default content type') raise web.HTTPError(406) - handler = settings[response_type] - content_type, data_bytes = handler.to_bytes(body) - if set_content_type: - self.set_header('Content-Type', content_type) - self.add_header('Vary', 'Accept') - self.write(data_bytes) + try: + handler = settings[response_type] + except KeyError: + self._logger.error( + 'no transcoder for the selected response content type %s, ' + 'is the default content type %r correct?', response_type, + settings.default_content_type) + raise web.HTTPError(500) + else: + content_type, data_bytes = handler.to_bytes(body) + if set_content_type: + self.set_header('Content-Type', content_type) + self.add_header('Vary', 'Accept') + self.write(data_bytes) diff --git a/tests.py b/tests.py index 5e1e672..ad1d1d7 100644 --- a/tests.py +++ b/tests.py @@ -150,6 +150,15 @@ class SendResponseTests(testing.AsyncHTTPTestCase): }) self.assertEqual(response.code, 406) + def test_misconfigured_default_content_type(self): + settings = content.get_settings(self.application, force_instance=True) + settings.default_content_type = 'application/xml' + response = self.fetch('/', + method='POST', + body='{}', + headers={'Content-Type': 'application/json'}) + self.assertEqual(response.code, 500) + class GetRequestBodyTests(testing.AsyncHTTPTestCase): def setUp(self):