diff --git a/nova/api/openstack/placement/handler.py b/nova/api/openstack/placement/handler.py index 5d5377f4c835..d10fadd8855b 100644 --- a/nova/api/openstack/placement/handler.py +++ b/nova/api/openstack/placement/handler.py @@ -107,7 +107,11 @@ def handle_405(environ, start_response): _methods = util.wsgi_path_item(environ, '_methods') headers = {} if _methods: - headers['allow'] = _methods + # Ensure allow header is a python 2 or 3 native string (thus + # not unicode in python 2 but stay a string in python 3) + # In the process done by Routes to save the allowed methods + # to its routing table they become unicode in py2. + headers['allow'] = str(_methods) raise webob.exc.HTTPMethodNotAllowed( _('The method specified is not allowed for this resource.'), headers=headers, json_formatter=util.json_error_formatter) diff --git a/nova/tests/functional/api/openstack/placement/test_placement_api.py b/nova/tests/functional/api/openstack/placement/test_placement_api.py index 9fadc70fd96a..42cbc75ab829 100644 --- a/nova/tests/functional/api/openstack/placement/test_placement_api.py +++ b/nova/tests/functional/api/openstack/placement/test_placement_api.py @@ -12,11 +12,16 @@ import os +import wsgi_intercept + from gabbi import driver from nova.tests import fixtures as nova_fixtures from nova.tests.functional.api.openstack.placement import fixtures +# Check that wsgi application response headers are always +# native str. +wsgi_intercept.STRICT_RESPONSE_HEADERS = True TESTS_DIR = 'gabbits' diff --git a/nova/tests/unit/api/openstack/placement/test_handler.py b/nova/tests/unit/api/openstack/placement/test_handler.py index b0a81e15efcd..6a07343978f3 100644 --- a/nova/tests/unit/api/openstack/placement/test_handler.py +++ b/nova/tests/unit/api/openstack/placement/test_handler.py @@ -92,12 +92,24 @@ class MapperTest(test.NoDBTestCase): action = self.mapper.match(environ=environ)['action'] self.assertEqual('hello', action) - def test_405(self): + def test_405_methods(self): environ = _environ(path='/hello', method='POST') result = self.mapper.match(environ=environ) self.assertEqual(handler.handle_405, result['action']) self.assertEqual('GET', result['_methods']) + def test_405_headers(self): + environ = _environ(path='/hello', method='POST') + error = self.assertRaises(webob.exc.HTTPMethodNotAllowed, + handler.dispatch, + environ, start_response, + self.mapper) + allow_header = error.headers['allow'] + self.assertEqual('GET', allow_header) + # PEP 3333 requires that headers be whatever the native str + # is in that version of Python. Never unicode. + self.assertEqual(str, type(allow_header)) + class PlacementLoggingTest(test.NoDBTestCase):