diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 8f7cafbc326c..e95cb612d395 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -96,8 +96,10 @@ class Request(wsgi.Request): content_type = possible_type if not content_type: - content_type = self.accept.best_match( + best_matches = self.accept.acceptable_offers( get_supported_content_types()) + if best_matches: + content_type = best_matches[0][0] self.environ['nova.best_content_type'] = (content_type or 'application/json') @@ -134,8 +136,19 @@ class Request(wsgi.Request): """ if not self.accept_language: return None - return self.accept_language.best_match( - i18n.get_available_languages()) + + # NOTE(takashin): To decide the default behavior, 'default' is + # preferred over 'default_tag' because that is return as it is when + # no match. This is also little tricky that 'default' value cannot be + # None. At least one of default_tag or default must be supplied as + # an argument to the method, to define the defaulting behavior. + # So passing a sentinal value to return None from this function. + best_match = self.accept_language.lookup( + i18n.get_available_languages(), default='fake_LANG') + + if best_match == 'fake_LANG': + best_match = None + return best_match def set_api_version_request(self): """Set API version request based on the request header information.""" diff --git a/nova/tests/unit/api/openstack/test_wsgi.py b/nova/tests/unit/api/openstack/test_wsgi.py index bf6dded7efc3..0078ea5fe7b8 100644 --- a/nova/tests/unit/api/openstack/test_wsgi.py +++ b/nova/tests/unit/api/openstack/test_wsgi.py @@ -50,7 +50,7 @@ class RequestTest(MicroversionedTest): super(RequestTest, self).setUp() self.stub_out('nova.i18n.get_available_languages', lambda *args, **kwargs: - ['en_GB', 'en_AU', 'de', 'zh_CN', 'en_US']) + ['en-GB', 'en-AU', 'de', 'zh-CN', 'en-US', 'ja-JP']) def test_content_type_missing(self): request = wsgi.Request.blank('/tests/123', method='POST') @@ -76,31 +76,49 @@ class RequestTest(MicroversionedTest): result = request.best_match_content_type() self.assertEqual(result, "application/json") + def test_content_type_accept_with_quality_values(self): + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = ( + "application/json;q=0.4," + "application/vnd.openstack.compute+json;q=0.6") + result = request.best_match_content_type() + self.assertEqual("application/vnd.openstack.compute+json", result) + def test_from_request(self): request = wsgi.Request.blank('/') accepted = 'bogus;q=1, en-gb;q=0.7,en-us,en;q=0.5,*;q=0.7' request.headers = {'Accept-Language': accepted} - self.assertEqual(request.best_match_language(), 'en_US') + self.assertEqual(request.best_match_language(), 'en-US') def test_asterisk(self): - # asterisk should match first available if there - # are not any other available matches + # In the section 3.4 of RFC4647, it says as follows: + # If the language range "*"(asterisk) is the only one + # in the language priority list or if no other language range + # follows, the default value is computed and returned. + # + # In this case, the default value 'None' is returned. request = wsgi.Request.blank('/') - accepted = '*,es;q=0.5' + accepted = '*;q=0.5' request.headers = {'Accept-Language': accepted} - self.assertEqual(request.best_match_language(), 'en_GB') + self.assertIsNone(request.best_match_language()) - def test_prefix(self): + def test_asterisk_followed_by_other_language(self): request = wsgi.Request.blank('/') - accepted = 'zh' + accepted = '*,ja-jp;q=0.5' request.headers = {'Accept-Language': accepted} - self.assertEqual(request.best_match_language(), 'zh_CN') + self.assertEqual('ja-JP', request.best_match_language()) + + def test_truncate(self): + request = wsgi.Request.blank('/') + accepted = 'de-CH' + request.headers = {'Accept-Language': accepted} + self.assertEqual('de', request.best_match_language()) def test_secondary(self): request = wsgi.Request.blank('/') accepted = 'nn,en-gb;q=0.5' request.headers = {'Accept-Language': accepted} - self.assertEqual(request.best_match_language(), 'en_GB') + self.assertEqual('en-GB', request.best_match_language()) def test_none_found(self): request = wsgi.Request.blank('/')