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
This commit is contained in:
Konstantin Snihyr 2016-02-09 16:01:13 +03:00
parent 3b8a895cd1
commit d663171fe3
4 changed files with 21 additions and 8 deletions

View File

@ -43,6 +43,8 @@ General information
* 403 ``Forbidden`` - access denied. * 403 ``Forbidden`` - access denied.
* 404 ``Not Found`` - resource was not found * 404 ``Not Found`` - resource was not found
* 405 ``Method Not Allowed`` - requested method is not supported for resource. * 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. * 409 ``Conflict`` - requested method resulted in a conflict with the current state of the resource.
* **Response of POSTs and PUTs** * **Response of POSTs and PUTs**

View File

@ -50,6 +50,11 @@ class UnsupportedContentType(OpenstackException):
msg_fmt = "Unsupported content type %(content_type)s" 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): class MalformedRequestBody(OpenstackException):
msg_fmt = "Malformed message body: %(reason)s" msg_fmt = "Malformed message body: %(reason)s"

View File

@ -306,7 +306,7 @@ class Request(webob.Request):
"""Determine the requested response content-type. """Determine the requested response content-type.
Based on the query extension then the Accept header. 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 supported_content_types = (supported_content_types or
@ -324,7 +324,7 @@ class Request(webob.Request):
bm = self.accept.best_match(supported_content_types) bm = self.accept.best_match(supported_content_types)
if not bm: if not bm:
raise exceptions.UnsupportedContentType(content_type=self.accept) raise exceptions.NotAcceptableContentType(content_type=self.accept)
return bm return bm
def get_content_type(self, allowed_content_types=None): def get_content_type(self, allowed_content_types=None):
@ -416,6 +416,9 @@ class Resource(object):
except exceptions.UnsupportedContentType: except exceptions.UnsupportedContentType:
msg = _("Unsupported Content-Type") msg = _("Unsupported Content-Type")
return webob.exc.HTTPUnsupportedMediaType(detail=msg) 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: except exceptions.MalformedRequestBody:
msg = _("Malformed request body") msg = _("Malformed request body")
return webob.exc.HTTPBadRequest(explanation=msg) return webob.exc.HTTPBadRequest(explanation=msg)

View File

@ -414,8 +414,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase):
result = req.get_response(self.api) result = req.get_response(self.api)
self.assertEqual(415, result.status_code) self.assertEqual(406, result.status_code)
self.assertTrue('Unsupported Content-Type' in result.body) self.assertTrue('Acceptable response can not be provided'
in result.body)
def test_get_ui_definition(self): def test_get_ui_definition(self):
self._set_policy_rules( self._set_policy_rules(
@ -447,8 +448,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase):
result = req.get_response(self.api) result = req.get_response(self.api)
self.assertEqual(415, result.status_code) self.assertEqual(406, result.status_code)
self.assertTrue('Unsupported Content-Type' in result.body) self.assertTrue('Acceptable response can not be provided'
in result.body)
def test_get_logo(self): def test_get_logo(self):
self._set_policy_rules( self._set_policy_rules(
@ -481,8 +483,9 @@ class TestCatalogApi(test_base.ControllerTest, test_base.MuranoApiTestCase):
result = req.get_response(self.api) result = req.get_response(self.api)
self.assertEqual(415, result.status_code) self.assertEqual(406, result.status_code)
self.assertTrue('Unsupported Content-Type' in result.body) self.assertTrue('Acceptable response can not be provided'
in result.body)
def test_add_public_unauthorized(self): def test_add_public_unauthorized(self):
self._set_policy_rules({ self._set_policy_rules({