diff --git a/django/http/utils.py b/django/http/utils.py index 5eea23907b..01808648ba 100644 --- a/django/http/utils.py +++ b/django/http/utils.py @@ -76,7 +76,8 @@ def fix_IE_for_vary(request, response): # The first part of the Content-Type field will be the MIME type, # everything after ';', such as character-set, can be ignored. - if response['Content-Type'].split(';')[0] not in safe_mime_types: + mime_type = response.get('Content-Type', '').partition(';')[0] + if mime_type not in safe_mime_types: try: del response['Vary'] except KeyError: diff --git a/tests/regressiontests/utils/http.py b/tests/regressiontests/utils/http.py index 83a4a7f54d..666d04f672 100644 --- a/tests/regressiontests/utils/http.py +++ b/tests/regressiontests/utils/http.py @@ -1,5 +1,7 @@ from django.utils import http from django.utils import unittest +from django.http import HttpResponse, utils +from django.test import RequestFactory class TestUtilsHttp(unittest.TestCase): @@ -21,3 +23,49 @@ class TestUtilsHttp(unittest.TestCase): self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com')) # Different port self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001')) + + def test_fix_IE_for_vary(self): + """ + Regression for #16632. + + `fix_IE_for_vary` shouldn't crash when there's no Content-Type header. + """ + + # functions to generate responses + def response_with_unsafe_content_type(): + r = HttpResponse(content_type="text/unsafe") + r['Vary'] = 'Cookie' + return r + + def no_content_response_with_unsafe_content_type(): + # 'Content-Type' always defaulted, so delete it + r = response_with_unsafe_content_type() + del r['Content-Type'] + return r + + # request with & without IE user agent + rf = RequestFactory() + request = rf.get('/') + ie_request = rf.get('/', HTTP_USER_AGENT='MSIE') + + # not IE, unsafe_content_type + response = response_with_unsafe_content_type() + utils.fix_IE_for_vary(request, response) + self.assertTrue('Vary' in response) + + # IE, unsafe_content_type + response = response_with_unsafe_content_type() + utils.fix_IE_for_vary(ie_request, response) + self.assertFalse('Vary' in response) + + # not IE, no_content + response = no_content_response_with_unsafe_content_type() + utils.fix_IE_for_vary(request, response) + self.assertTrue('Vary' in response) + + # IE, no_content + response = no_content_response_with_unsafe_content_type() + utils.fix_IE_for_vary(ie_request, response) + self.assertFalse('Vary' in response) + +