Merge pull request #796 from ambv/vary

Fixes #17866: Vary: Accept-Language header when language prefix used
This commit is contained in:
Honza Král 2013-02-23 12:32:30 -08:00
commit c2a045198c
5 changed files with 42 additions and 13 deletions

View File

@ -17,6 +17,14 @@ class LocaleMiddleware(object):
is available, of course). is available, of course).
""" """
def __init__(self):
self._supported_languages = dict(settings.LANGUAGES)
self._is_language_prefix_patterns_used = False
for url_pattern in get_resolver(None).url_patterns:
if isinstance(url_pattern, LocaleRegexURLResolver):
self._is_language_prefix_patterns_used = True
break
def process_request(self, request): def process_request(self, request):
check_path = self.is_language_prefix_patterns_used() check_path = self.is_language_prefix_patterns_used()
language = translation.get_language_from_request( language = translation.get_language_from_request(
@ -26,9 +34,11 @@ class LocaleMiddleware(object):
def process_response(self, request, response): def process_response(self, request, response):
language = translation.get_language() language = translation.get_language()
if (response.status_code == 404 and language_from_path = translation.get_language_from_path(
not translation.get_language_from_path(request.path_info) request.path_info, supported=self._supported_languages
and self.is_language_prefix_patterns_used()): )
if (response.status_code == 404 and not language_from_path
and self.is_language_prefix_patterns_used()):
urlconf = getattr(request, 'urlconf', None) urlconf = getattr(request, 'urlconf', None)
language_path = '/%s%s' % (language, request.path_info) language_path = '/%s%s' % (language, request.path_info)
path_valid = is_valid_path(language_path, urlconf) path_valid = is_valid_path(language_path, urlconf)
@ -42,8 +52,9 @@ class LocaleMiddleware(object):
request.get_host(), language, request.get_full_path()) request.get_host(), language, request.get_full_path())
return HttpResponseRedirect(language_url) return HttpResponseRedirect(language_url)
translation.deactivate() translation.deactivate()
if not (self.is_language_prefix_patterns_used()
patch_vary_headers(response, ('Accept-Language',)) and language_from_path):
patch_vary_headers(response, ('Accept-Language',))
if 'Content-Language' not in response: if 'Content-Language' not in response:
response['Content-Language'] = language response['Content-Language'] = language
return response return response
@ -53,7 +64,4 @@ class LocaleMiddleware(object):
Returns `True` if the `LocaleRegexURLResolver` is used Returns `True` if the `LocaleRegexURLResolver` is used
at root level of the urlpatterns, else it returns `False`. at root level of the urlpatterns, else it returns `False`.
""" """
for url_pattern in get_resolver(None).url_patterns: return self._is_language_prefix_patterns_used
if isinstance(url_pattern, LocaleRegexURLResolver):
return True
return False

View File

@ -165,8 +165,8 @@ def to_locale(language):
def get_language_from_request(request, check_path=False): def get_language_from_request(request, check_path=False):
return _trans.get_language_from_request(request, check_path) return _trans.get_language_from_request(request, check_path)
def get_language_from_path(path): def get_language_from_path(path, supported=None):
return _trans.get_language_from_path(path) return _trans.get_language_from_path(path, supported=supported)
def templatize(src, origin=None): def templatize(src, origin=None):
return _trans.templatize(src, origin) return _trans.templatize(src, origin)

View File

@ -58,6 +58,6 @@ def to_locale(language):
def get_language_from_request(request, check_path=False): def get_language_from_request(request, check_path=False):
return settings.LANGUAGE_CODE return settings.LANGUAGE_CODE
def get_language_from_path(request): def get_language_from_path(request, supported=None):
return None return None

View File

@ -172,6 +172,26 @@ class URLRedirectTests(URLTestCaseBase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
class URLVaryAcceptLanguageTests(URLTestCaseBase):
"""
Tests that 'Accept-Language' is not added to the Vary header when using
prefixed URLs.
"""
def test_no_prefix_response(self):
response = self.client.get('/not-prefixed/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.get('Vary'), 'Accept-Language')
def test_en_redirect(self):
response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en')
self.assertRedirects(response, '/en/account/register/')
self.assertFalse(response.get('Vary'))
response = self.client.get(response['location'])
self.assertEqual(response.status_code, 200)
self.assertFalse(response.get('Vary'))
class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase): class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase):
""" """
Tests the redirect when the requested URL doesn't end with a slash Tests the redirect when the requested URL doesn't end with a slash

View File

@ -48,7 +48,8 @@ from .models import Company, TestModel
from .patterns.tests import (URLRedirectWithoutTrailingSlashTests, from .patterns.tests import (URLRedirectWithoutTrailingSlashTests,
URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase, URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase,
URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests, URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests,
URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests) URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests,
URLVaryAcceptLanguageTests)
here = os.path.dirname(os.path.abspath(upath(__file__))) here = os.path.dirname(os.path.abspath(upath(__file__)))