From d663171fe33edb2b70e1603ce1810698819d8ba6 Mon Sep 17 00:00:00 2001 From: Konstantin Snihyr Date: Tue, 9 Feb 2016 16:01:13 +0300 Subject: [PATCH] Replace HTTP 415 return code to HTTP 406 when it's correct Server must return HTTP 406 code when content type, specified in "Accept" header unexpected or unknown Otherwise server must return HTTP 415 code. For example, if content type parsed from "Content-Type" Change-Id: Ic85d1ad9e44ae722dca347b9f1dd643ba3490062 Closes-Bug: #1512390 --- doc/source/specification/index.rst | 2 ++ murano/common/exceptions.py | 5 +++++ murano/common/wsgi.py | 7 +++++-- murano/tests/unit/api/v1/test_catalog.py | 15 +++++++++------ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/doc/source/specification/index.rst b/doc/source/specification/index.rst index 045b9f3d..d245cd63 100644 --- a/doc/source/specification/index.rst +++ b/doc/source/specification/index.rst @@ -43,6 +43,8 @@ General information * 403 ``Forbidden`` - access denied. * 404 ``Not Found`` - resource was not found * 405 ``Method Not Allowed`` - requested method is not supported for resource. + * 406 ``Not Acceptable`` - the requested resource is only capable of generating content not acceptable + according to the Accept headers sent in the request. * 409 ``Conflict`` - requested method resulted in a conflict with the current state of the resource. * **Response of POSTs and PUTs** diff --git a/murano/common/exceptions.py b/murano/common/exceptions.py index 44258a0a..cafa8b18 100644 --- a/murano/common/exceptions.py +++ b/murano/common/exceptions.py @@ -50,6 +50,11 @@ class UnsupportedContentType(OpenstackException): msg_fmt = "Unsupported content type %(content_type)s" +class NotAcceptableContentType(OpenstackException): + msg_fmt = ("Response with content type %(content_type)s " + "expected but can not be provided") + + class MalformedRequestBody(OpenstackException): msg_fmt = "Malformed message body: %(reason)s" diff --git a/murano/common/wsgi.py b/murano/common/wsgi.py index 4bf8f14c..21383705 100644 --- a/murano/common/wsgi.py +++ b/murano/common/wsgi.py @@ -306,7 +306,7 @@ class Request(webob.Request): """Determine the requested response content-type. Based on the query extension then the Accept header. - Raise UnsupportedContentType exception if we don't find a preference + Raise NotAcceptableContentType exception if we don't find a preference """ supported_content_types = (supported_content_types or @@ -324,7 +324,7 @@ class Request(webob.Request): bm = self.accept.best_match(supported_content_types) if not bm: - raise exceptions.UnsupportedContentType(content_type=self.accept) + raise exceptions.NotAcceptableContentType(content_type=self.accept) return bm def get_content_type(self, allowed_content_types=None): @@ -416,6 +416,9 @@ class Resource(object): except exceptions.UnsupportedContentType: msg = _("Unsupported Content-Type") return webob.exc.HTTPUnsupportedMediaType(detail=msg) + except exceptions.NotAcceptableContentType: + msg = _("Acceptable response can not be provided") + return webob.exc.HTTPNotAcceptable(detail=msg) except exceptions.MalformedRequestBody: msg = _("Malformed request body") return webob.exc.HTTPBadRequest(explanation=msg) diff --git a/murano/tests/unit/api/v1/test_catalog.py b/murano/tests/unit/api/v1/test_catalog.py index 19a731d7..7b84eeca 100644 --- a/murano/tests/unit/api/v1/test_catalog.py +++ b/murano/tests/unit/api/v1/test_catalog.py @@ -414,8 +414,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase): result = req.get_response(self.api) - self.assertEqual(415, result.status_code) - self.assertTrue('Unsupported Content-Type' in result.body) + self.assertEqual(406, result.status_code) + self.assertTrue('Acceptable response can not be provided' + in result.body) def test_get_ui_definition(self): self._set_policy_rules( @@ -447,8 +448,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase): result = req.get_response(self.api) - self.assertEqual(415, result.status_code) - self.assertTrue('Unsupported Content-Type' in result.body) + self.assertEqual(406, result.status_code) + self.assertTrue('Acceptable response can not be provided' + in result.body) def test_get_logo(self): self._set_policy_rules( @@ -481,8 +483,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase): result = req.get_response(self.api) - self.assertEqual(415, result.status_code) - self.assertTrue('Unsupported Content-Type' in result.body) + self.assertEqual(406, result.status_code) + self.assertTrue('Acceptable response can not be provided' + in result.body) def test_add_public_unauthorized(self): self._set_policy_rules({