1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, unicode_literals
10
from django.conf import settings
11
from django.core import mail
12
from django.db import (transaction, connections, DEFAULT_DB_ALIAS,
14
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
15
from django.middleware.clickjacking import XFrameOptionsMiddleware
16
from django.middleware.common import CommonMiddleware, BrokenLinkEmailsMiddleware
17
from django.middleware.http import ConditionalGetMiddleware
18
from django.middleware.gzip import GZipMiddleware
19
from django.middleware.transaction import TransactionMiddleware
20
from django.test import TransactionTestCase, TestCase, RequestFactory
21
from django.test.utils import override_settings, IgnorePendingDeprecationWarningsMixin
22
from django.utils import six
23
from django.utils.encoding import force_str
24
from django.utils.six.moves import xrange
25
from django.utils.unittest import expectedFailure, skipIf
27
from .models import Band
30
class CommonMiddlewareTest(TestCase):
32
def _get_request(self, path):
33
request = HttpRequest()
35
'SERVER_NAME': 'testserver',
38
request.path = request.path_info = "/middleware/%s" % path
41
@override_settings(APPEND_SLASH=True)
42
def test_append_slash_have_slash(self):
44
Tests that URLs with slashes go unmolested.
46
request = self._get_request('slash/')
47
self.assertEqual(CommonMiddleware().process_request(request), None)
49
@override_settings(APPEND_SLASH=True)
50
def test_append_slash_slashless_resource(self):
52
Tests that matches to explicit slashless URLs go unmolested.
54
request = self._get_request('noslash')
55
self.assertEqual(CommonMiddleware().process_request(request), None)
57
@override_settings(APPEND_SLASH=True)
58
def test_append_slash_slashless_unknown(self):
60
Tests that APPEND_SLASH doesn't redirect to unknown resources.
62
request = self._get_request('unknown')
63
self.assertEqual(CommonMiddleware().process_request(request), None)
65
@override_settings(APPEND_SLASH=True)
66
def test_append_slash_redirect(self):
68
Tests that APPEND_SLASH redirects slashless URLs to a valid pattern.
70
request = self._get_request('slash')
71
r = CommonMiddleware().process_request(request)
72
self.assertEqual(r.status_code, 301)
73
self.assertEqual(r.url, 'http://testserver/middleware/slash/')
75
@override_settings(APPEND_SLASH=True, DEBUG=True)
76
def test_append_slash_no_redirect_on_POST_in_DEBUG(self):
78
Tests that while in debug mode, an exception is raised with a warning
79
when a failed attempt is made to POST to an URL which would normally be
80
redirected to a slashed version.
82
request = self._get_request('slash')
83
request.method = 'POST'
84
with six.assertRaisesRegex(self, RuntimeError, 'end in a slash'):
85
CommonMiddleware().process_request(request)
87
@override_settings(APPEND_SLASH=False)
88
def test_append_slash_disabled(self):
90
Tests disabling append slash functionality.
92
request = self._get_request('slash')
93
self.assertEqual(CommonMiddleware().process_request(request), None)
95
@override_settings(APPEND_SLASH=True)
96
def test_append_slash_quoted(self):
98
Tests that URLs which require quoting are redirected to their slash
101
request = self._get_request('needsquoting#')
102
r = CommonMiddleware().process_request(request)
103
self.assertEqual(r.status_code, 301)
106
'http://testserver/middleware/needsquoting%23/')
108
@override_settings(APPEND_SLASH=False, PREPEND_WWW=True)
109
def test_prepend_www(self):
110
request = self._get_request('path/')
111
r = CommonMiddleware().process_request(request)
112
self.assertEqual(r.status_code, 301)
115
'http://www.testserver/middleware/path/')
117
@override_settings(APPEND_SLASH=True, PREPEND_WWW=True)
118
def test_prepend_www_append_slash_have_slash(self):
119
request = self._get_request('slash/')
120
r = CommonMiddleware().process_request(request)
121
self.assertEqual(r.status_code, 301)
122
self.assertEqual(r.url,
123
'http://www.testserver/middleware/slash/')
125
@override_settings(APPEND_SLASH=True, PREPEND_WWW=True)
126
def test_prepend_www_append_slash_slashless(self):
127
request = self._get_request('slash')
128
r = CommonMiddleware().process_request(request)
129
self.assertEqual(r.status_code, 301)
130
self.assertEqual(r.url,
131
'http://www.testserver/middleware/slash/')
134
# The following tests examine expected behavior given a custom urlconf that
135
# overrides the default one through the request object.
137
@override_settings(APPEND_SLASH=True)
138
def test_append_slash_have_slash_custom_urlconf(self):
140
Tests that URLs with slashes go unmolested.
142
request = self._get_request('customurlconf/slash/')
143
request.urlconf = 'middleware.extra_urls'
144
self.assertEqual(CommonMiddleware().process_request(request), None)
146
@override_settings(APPEND_SLASH=True)
147
def test_append_slash_slashless_resource_custom_urlconf(self):
149
Tests that matches to explicit slashless URLs go unmolested.
151
request = self._get_request('customurlconf/noslash')
152
request.urlconf = 'middleware.extra_urls'
153
self.assertEqual(CommonMiddleware().process_request(request), None)
155
@override_settings(APPEND_SLASH=True)
156
def test_append_slash_slashless_unknown_custom_urlconf(self):
158
Tests that APPEND_SLASH doesn't redirect to unknown resources.
160
request = self._get_request('customurlconf/unknown')
161
request.urlconf = 'middleware.extra_urls'
162
self.assertEqual(CommonMiddleware().process_request(request), None)
164
@override_settings(APPEND_SLASH=True)
165
def test_append_slash_redirect_custom_urlconf(self):
167
Tests that APPEND_SLASH redirects slashless URLs to a valid pattern.
169
request = self._get_request('customurlconf/slash')
170
request.urlconf = 'middleware.extra_urls'
171
r = CommonMiddleware().process_request(request)
172
self.assertFalse(r is None,
173
"CommonMiddlware failed to return APPEND_SLASH redirect using request.urlconf")
174
self.assertEqual(r.status_code, 301)
175
self.assertEqual(r.url, 'http://testserver/middleware/customurlconf/slash/')
177
@override_settings(APPEND_SLASH=True, DEBUG=True)
178
def test_append_slash_no_redirect_on_POST_in_DEBUG_custom_urlconf(self):
180
Tests that while in debug mode, an exception is raised with a warning
181
when a failed attempt is made to POST to an URL which would normally be
182
redirected to a slashed version.
184
request = self._get_request('customurlconf/slash')
185
request.urlconf = 'middleware.extra_urls'
186
request.method = 'POST'
187
with six.assertRaisesRegex(self, RuntimeError, 'end in a slash'):
188
CommonMiddleware().process_request(request)
190
@override_settings(APPEND_SLASH=False)
191
def test_append_slash_disabled_custom_urlconf(self):
193
Tests disabling append slash functionality.
195
request = self._get_request('customurlconf/slash')
196
request.urlconf = 'middleware.extra_urls'
197
self.assertEqual(CommonMiddleware().process_request(request), None)
199
@override_settings(APPEND_SLASH=True)
200
def test_append_slash_quoted_custom_urlconf(self):
202
Tests that URLs which require quoting are redirected to their slash
205
request = self._get_request('customurlconf/needsquoting#')
206
request.urlconf = 'middleware.extra_urls'
207
r = CommonMiddleware().process_request(request)
208
self.assertFalse(r is None,
209
"CommonMiddlware failed to return APPEND_SLASH redirect using request.urlconf")
210
self.assertEqual(r.status_code, 301)
213
'http://testserver/middleware/customurlconf/needsquoting%23/')
215
@override_settings(APPEND_SLASH=False, PREPEND_WWW=True)
216
def test_prepend_www_custom_urlconf(self):
217
request = self._get_request('customurlconf/path/')
218
request.urlconf = 'middleware.extra_urls'
219
r = CommonMiddleware().process_request(request)
220
self.assertEqual(r.status_code, 301)
223
'http://www.testserver/middleware/customurlconf/path/')
225
@override_settings(APPEND_SLASH=True, PREPEND_WWW=True)
226
def test_prepend_www_append_slash_have_slash_custom_urlconf(self):
227
request = self._get_request('customurlconf/slash/')
228
request.urlconf = 'middleware.extra_urls'
229
r = CommonMiddleware().process_request(request)
230
self.assertEqual(r.status_code, 301)
231
self.assertEqual(r.url,
232
'http://www.testserver/middleware/customurlconf/slash/')
234
@override_settings(APPEND_SLASH=True, PREPEND_WWW=True)
235
def test_prepend_www_append_slash_slashless_custom_urlconf(self):
236
request = self._get_request('customurlconf/slash')
237
request.urlconf = 'middleware.extra_urls'
238
r = CommonMiddleware().process_request(request)
239
self.assertEqual(r.status_code, 301)
240
self.assertEqual(r.url,
241
'http://www.testserver/middleware/customurlconf/slash/')
243
# Legacy tests for the 404 error reporting via email (to be removed in 1.8)
245
@override_settings(IGNORABLE_404_URLS=(re.compile(r'foo'),),
246
SEND_BROKEN_LINK_EMAILS=True,
247
MANAGERS=('PHB@dilbert.com',))
248
def test_404_error_reporting(self):
249
request = self._get_request('regular_url/that/does/not/exist')
250
request.META['HTTP_REFERER'] = '/another/url/'
251
with warnings.catch_warnings():
252
warnings.simplefilter("ignore", PendingDeprecationWarning)
253
response = self.client.get(request.path)
254
CommonMiddleware().process_response(request, response)
255
self.assertEqual(len(mail.outbox), 1)
256
self.assertIn('Broken', mail.outbox[0].subject)
258
@override_settings(IGNORABLE_404_URLS=(re.compile(r'foo'),),
259
SEND_BROKEN_LINK_EMAILS=True,
260
MANAGERS=('PHB@dilbert.com',))
261
def test_404_error_reporting_no_referer(self):
262
request = self._get_request('regular_url/that/does/not/exist')
263
with warnings.catch_warnings():
264
warnings.simplefilter("ignore", PendingDeprecationWarning)
265
response = self.client.get(request.path)
266
CommonMiddleware().process_response(request, response)
267
self.assertEqual(len(mail.outbox), 0)
269
@override_settings(IGNORABLE_404_URLS=(re.compile(r'foo'),),
270
SEND_BROKEN_LINK_EMAILS=True,
271
MANAGERS=('PHB@dilbert.com',))
272
def test_404_error_reporting_ignored_url(self):
273
request = self._get_request('foo_url/that/does/not/exist/either')
274
request.META['HTTP_REFERER'] = '/another/url/'
275
with warnings.catch_warnings():
276
warnings.simplefilter("ignore", PendingDeprecationWarning)
277
response = self.client.get(request.path)
278
CommonMiddleware().process_response(request, response)
279
self.assertEqual(len(mail.outbox), 0)
283
def test_non_ascii_query_string_does_not_crash(self):
284
"""Regression test for #15152"""
285
request = self._get_request('slash')
286
request.META['QUERY_STRING'] = force_str('drink=café')
287
response = CommonMiddleware().process_request(request)
288
self.assertEqual(response.status_code, 301)
292
IGNORABLE_404_URLS=(re.compile(r'foo'),),
293
MANAGERS=('PHB@dilbert.com',),
295
class BrokenLinkEmailsMiddlewareTest(TestCase):
298
self.req = HttpRequest()
300
'SERVER_NAME': 'testserver',
303
self.req.path = self.req.path_info = 'regular_url/that/does/not/exist'
304
self.resp = self.client.get(self.req.path)
306
def test_404_error_reporting(self):
307
self.req.META['HTTP_REFERER'] = '/another/url/'
308
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
309
self.assertEqual(len(mail.outbox), 1)
310
self.assertIn('Broken', mail.outbox[0].subject)
312
def test_404_error_reporting_no_referer(self):
313
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
314
self.assertEqual(len(mail.outbox), 0)
316
def test_404_error_reporting_ignored_url(self):
317
self.req.path = self.req.path_info = 'foo_url/that/does/not/exist'
318
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
319
self.assertEqual(len(mail.outbox), 0)
321
@skipIf(six.PY3, "HTTP_REFERER is str type on Python 3")
322
def test_404_error_nonascii_referrer(self):
323
# Such referer strings should not happen, but anyway, if it happens,
325
self.req.META['HTTP_REFERER'] = b'http://testserver/c/\xd0\xbb\xd0\xb8/'
326
BrokenLinkEmailsMiddleware().process_response(self.req, self.resp)
327
self.assertEqual(len(mail.outbox), 1)
329
def test_custom_request_checker(self):
330
class SubclassedMiddleware(BrokenLinkEmailsMiddleware):
331
ignored_user_agent_patterns = (re.compile(r'Spider.*'),
332
re.compile(r'Robot.*'))
333
def is_ignorable_request(self, request, uri, domain, referer):
334
'''Check user-agent in addition to normal checks.'''
335
if super(SubclassedMiddleware, self).is_ignorable_request(request, uri, domain, referer):
337
user_agent = request.META['HTTP_USER_AGENT']
338
return any(pattern.search(user_agent) for pattern in
339
self.ignored_user_agent_patterns)
341
self.req.META['HTTP_REFERER'] = '/another/url/'
342
self.req.META['HTTP_USER_AGENT'] = 'Spider machine 3.4'
343
SubclassedMiddleware().process_response(self.req, self.resp)
344
self.assertEqual(len(mail.outbox), 0)
345
self.req.META['HTTP_USER_AGENT'] = 'My user agent'
346
SubclassedMiddleware().process_response(self.req, self.resp)
347
self.assertEqual(len(mail.outbox), 1)
349
class ConditionalGetMiddlewareTest(TestCase):
350
urls = 'middleware.cond_get_urls'
352
self.req = HttpRequest()
354
'SERVER_NAME': 'testserver',
357
self.req.path = self.req.path_info = "/"
358
self.resp = self.client.get(self.req.path)
360
# Tests for the Date header
362
def test_date_header_added(self):
363
self.assertFalse('Date' in self.resp)
364
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
365
self.assertTrue('Date' in self.resp)
367
# Tests for the Content-Length header
369
def test_content_length_header_added(self):
370
content_length = len(self.resp.content)
371
self.assertFalse('Content-Length' in self.resp)
372
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
373
self.assertTrue('Content-Length' in self.resp)
374
self.assertEqual(int(self.resp['Content-Length']), content_length)
376
def test_content_length_header_not_added(self):
377
resp = StreamingHttpResponse('content')
378
self.assertFalse('Content-Length' in resp)
379
resp = ConditionalGetMiddleware().process_response(self.req, resp)
380
self.assertFalse('Content-Length' in resp)
382
def test_content_length_header_not_changed(self):
383
bad_content_length = len(self.resp.content) + 10
384
self.resp['Content-Length'] = bad_content_length
385
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
386
self.assertEqual(int(self.resp['Content-Length']), bad_content_length)
388
# Tests for the ETag header
390
def test_if_none_match_and_no_etag(self):
391
self.req.META['HTTP_IF_NONE_MATCH'] = 'spam'
392
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
393
self.assertEqual(self.resp.status_code, 200)
395
def test_no_if_none_match_and_etag(self):
396
self.resp['ETag'] = 'eggs'
397
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
398
self.assertEqual(self.resp.status_code, 200)
400
def test_if_none_match_and_same_etag(self):
401
self.req.META['HTTP_IF_NONE_MATCH'] = self.resp['ETag'] = 'spam'
402
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
403
self.assertEqual(self.resp.status_code, 304)
405
def test_if_none_match_and_different_etag(self):
406
self.req.META['HTTP_IF_NONE_MATCH'] = 'spam'
407
self.resp['ETag'] = 'eggs'
408
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
409
self.assertEqual(self.resp.status_code, 200)
411
@override_settings(USE_ETAGS=True)
414
res = HttpResponse('content')
416
CommonMiddleware().process_response(req, res).has_header('ETag'))
418
@override_settings(USE_ETAGS=True)
419
def test_etag_streaming_response(self):
421
res = StreamingHttpResponse(['content'])
422
res['ETag'] = 'tomatoes'
424
CommonMiddleware().process_response(req, res).get('ETag'),
427
@override_settings(USE_ETAGS=True)
428
def test_no_etag_streaming_response(self):
430
res = StreamingHttpResponse(['content'])
432
CommonMiddleware().process_response(req, res).has_header('ETag'))
434
# Tests for the Last-Modified header
436
def test_if_modified_since_and_no_last_modified(self):
437
self.req.META['HTTP_IF_MODIFIED_SINCE'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
438
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
439
self.assertEqual(self.resp.status_code, 200)
441
def test_no_if_modified_since_and_last_modified(self):
442
self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
443
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
444
self.assertEqual(self.resp.status_code, 200)
446
def test_if_modified_since_and_same_last_modified(self):
447
self.req.META['HTTP_IF_MODIFIED_SINCE'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
448
self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
449
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
450
self.assertEqual(self.resp.status_code, 304)
452
def test_if_modified_since_and_last_modified_in_the_past(self):
453
self.req.META['HTTP_IF_MODIFIED_SINCE'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
454
self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:35:44 GMT'
455
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
456
self.assertEqual(self.resp.status_code, 304)
458
def test_if_modified_since_and_last_modified_in_the_future(self):
459
self.req.META['HTTP_IF_MODIFIED_SINCE'] = 'Sat, 12 Feb 2011 17:38:44 GMT'
460
self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:41:44 GMT'
461
self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp)
462
self.assertEqual(self.resp.status_code, 200)
465
class XFrameOptionsMiddlewareTest(TestCase):
467
Tests for the X-Frame-Options clickjacking prevention middleware.
470
def test_same_origin(self):
472
Tests that the X_FRAME_OPTIONS setting can be set to SAMEORIGIN to
473
have the middleware use that value for the HTTP header.
475
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
476
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
478
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
480
with override_settings(X_FRAME_OPTIONS='sameorigin'):
481
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
483
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
487
Tests that the X_FRAME_OPTIONS setting can be set to DENY to
488
have the middleware use that value for the HTTP header.
490
with override_settings(X_FRAME_OPTIONS='DENY'):
491
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
493
self.assertEqual(r['X-Frame-Options'], 'DENY')
495
with override_settings(X_FRAME_OPTIONS='deny'):
496
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
498
self.assertEqual(r['X-Frame-Options'], 'DENY')
500
def test_defaults_sameorigin(self):
502
Tests that if the X_FRAME_OPTIONS setting is not set then it defaults
505
with override_settings(X_FRAME_OPTIONS=None):
506
del settings.X_FRAME_OPTIONS # restored by override_settings
507
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
509
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
511
def test_dont_set_if_set(self):
513
Tests that if the X-Frame-Options header is already set then the
514
middleware does not attempt to override it.
516
with override_settings(X_FRAME_OPTIONS='DENY'):
517
response = HttpResponse()
518
response['X-Frame-Options'] = 'SAMEORIGIN'
519
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
521
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
523
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
524
response = HttpResponse()
525
response['X-Frame-Options'] = 'DENY'
526
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
528
self.assertEqual(r['X-Frame-Options'], 'DENY')
530
def test_response_exempt(self):
532
Tests that if the response has a xframe_options_exempt attribute set
533
to False then it still sets the header, but if it's set to True then
536
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
537
response = HttpResponse()
538
response.xframe_options_exempt = False
539
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
541
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
543
response = HttpResponse()
544
response.xframe_options_exempt = True
545
r = XFrameOptionsMiddleware().process_response(HttpRequest(),
547
self.assertEqual(r.get('X-Frame-Options', None), None)
549
def test_is_extendable(self):
551
Tests that the XFrameOptionsMiddleware method that determines the
552
X-Frame-Options header value can be overridden based on something in
553
the request or response.
555
class OtherXFrameOptionsMiddleware(XFrameOptionsMiddleware):
556
# This is just an example for testing purposes...
557
def get_xframe_options_value(self, request, response):
558
if getattr(request, 'sameorigin', False):
560
if getattr(response, 'sameorigin', False):
564
with override_settings(X_FRAME_OPTIONS='DENY'):
565
response = HttpResponse()
566
response.sameorigin = True
567
r = OtherXFrameOptionsMiddleware().process_response(HttpRequest(),
569
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
571
request = HttpRequest()
572
request.sameorigin = True
573
r = OtherXFrameOptionsMiddleware().process_response(request,
575
self.assertEqual(r['X-Frame-Options'], 'SAMEORIGIN')
577
with override_settings(X_FRAME_OPTIONS='SAMEORIGIN'):
578
r = OtherXFrameOptionsMiddleware().process_response(HttpRequest(),
580
self.assertEqual(r['X-Frame-Options'], 'DENY')
583
class GZipMiddlewareTest(TestCase):
585
Tests the GZip middleware.
587
short_string = b"This string is too short to be worth compressing."
588
compressible_string = b'a' * 500
589
uncompressible_string = b''.join(six.int2byte(random.randint(0, 255)) for _ in xrange(500))
590
sequence = [b'a' * 500, b'b' * 200, b'a' * 300]
593
self.req = HttpRequest()
595
'SERVER_NAME': 'testserver',
598
self.req.path = self.req.path_info = "/"
599
self.req.META['HTTP_ACCEPT_ENCODING'] = 'gzip, deflate'
600
self.req.META['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1'
601
self.resp = HttpResponse()
602
self.resp.status_code = 200
603
self.resp.content = self.compressible_string
604
self.resp['Content-Type'] = 'text/html; charset=UTF-8'
605
self.stream_resp = StreamingHttpResponse(self.sequence)
606
self.stream_resp['Content-Type'] = 'text/html; charset=UTF-8'
609
def decompress(gzipped_string):
610
return gzip.GzipFile(mode='rb', fileobj=BytesIO(gzipped_string)).read()
612
def test_compress_response(self):
614
Tests that compression is performed on responses with compressible content.
616
r = GZipMiddleware().process_response(self.req, self.resp)
617
self.assertEqual(self.decompress(r.content), self.compressible_string)
618
self.assertEqual(r.get('Content-Encoding'), 'gzip')
619
self.assertEqual(r.get('Content-Length'), str(len(r.content)))
621
def test_compress_streaming_response(self):
623
Tests that compression is performed on responses with streaming content.
625
r = GZipMiddleware().process_response(self.req, self.stream_resp)
626
self.assertEqual(self.decompress(b''.join(r)), b''.join(self.sequence))
627
self.assertEqual(r.get('Content-Encoding'), 'gzip')
628
self.assertFalse(r.has_header('Content-Length'))
630
def test_compress_non_200_response(self):
632
Tests that compression is performed on responses with a status other than 200.
635
self.resp.status_code = 404
636
r = GZipMiddleware().process_response(self.req, self.resp)
637
self.assertEqual(self.decompress(r.content), self.compressible_string)
638
self.assertEqual(r.get('Content-Encoding'), 'gzip')
640
def test_no_compress_short_response(self):
642
Tests that compression isn't performed on responses with short content.
644
self.resp.content = self.short_string
645
r = GZipMiddleware().process_response(self.req, self.resp)
646
self.assertEqual(r.content, self.short_string)
647
self.assertEqual(r.get('Content-Encoding'), None)
649
def test_no_compress_compressed_response(self):
651
Tests that compression isn't performed on responses that are already compressed.
653
self.resp['Content-Encoding'] = 'deflate'
654
r = GZipMiddleware().process_response(self.req, self.resp)
655
self.assertEqual(r.content, self.compressible_string)
656
self.assertEqual(r.get('Content-Encoding'), 'deflate')
658
def test_no_compress_ie_js_requests(self):
660
Tests that compression isn't performed on JavaScript requests from Internet Explorer.
662
self.req.META['HTTP_USER_AGENT'] = 'Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)'
663
self.resp['Content-Type'] = 'application/javascript; charset=UTF-8'
664
r = GZipMiddleware().process_response(self.req, self.resp)
665
self.assertEqual(r.content, self.compressible_string)
666
self.assertEqual(r.get('Content-Encoding'), None)
668
def test_no_compress_uncompressible_response(self):
670
Tests that compression isn't performed on responses with uncompressible content.
672
self.resp.content = self.uncompressible_string
673
r = GZipMiddleware().process_response(self.req, self.resp)
674
self.assertEqual(r.content, self.uncompressible_string)
675
self.assertEqual(r.get('Content-Encoding'), None)
678
@override_settings(USE_ETAGS=True)
679
class ETagGZipMiddlewareTest(TestCase):
681
Tests if the ETag middleware behaves correctly with GZip middleware.
683
compressible_string = b'a' * 500
686
self.rf = RequestFactory()
688
def test_compress_response(self):
690
Tests that ETag is changed after gzip compression is performed.
692
request = self.rf.get('/', HTTP_ACCEPT_ENCODING='gzip, deflate')
693
response = GZipMiddleware().process_response(request,
694
CommonMiddleware().process_response(request,
695
HttpResponse(self.compressible_string)))
696
gzip_etag = response.get('ETag')
698
request = self.rf.get('/', HTTP_ACCEPT_ENCODING='')
699
response = GZipMiddleware().process_response(request,
700
CommonMiddleware().process_response(request,
701
HttpResponse(self.compressible_string)))
702
nogzip_etag = response.get('ETag')
704
self.assertNotEqual(gzip_etag, nogzip_etag)
706
class TransactionMiddlewareTest(IgnorePendingDeprecationWarningsMixin, TransactionTestCase):
708
Test the transaction middleware.
711
available_apps = ['middleware']
714
super(TransactionMiddlewareTest, self).setUp()
715
self.request = HttpRequest()
716
self.request.META = {
717
'SERVER_NAME': 'testserver',
720
self.request.path = self.request.path_info = "/"
721
self.response = HttpResponse()
722
self.response.status_code = 200
726
super(TransactionMiddlewareTest, self).tearDown()
728
def test_request(self):
729
TransactionMiddleware().process_request(self.request)
730
self.assertFalse(transaction.get_autocommit())
732
def test_managed_response(self):
733
transaction.enter_transaction_management()
734
Band.objects.create(name='The Beatles')
735
self.assertTrue(transaction.is_dirty())
736
TransactionMiddleware().process_response(self.request, self.response)
737
self.assertFalse(transaction.is_dirty())
738
self.assertEqual(Band.objects.count(), 1)
740
def test_exception(self):
741
transaction.enter_transaction_management()
742
Band.objects.create(name='The Beatles')
743
self.assertTrue(transaction.is_dirty())
744
TransactionMiddleware().process_exception(self.request, None)
745
self.assertFalse(transaction.is_dirty())
746
self.assertEqual(Band.objects.count(), 0)
748
def test_failing_commit(self):
749
# It is possible that connection.commit() fails. Check that
750
# TransactionMiddleware handles such cases correctly.
752
def raise_exception():
753
raise IntegrityError()
754
connections[DEFAULT_DB_ALIAS].commit = raise_exception
755
transaction.enter_transaction_management()
756
Band.objects.create(name='The Beatles')
757
self.assertTrue(transaction.is_dirty())
758
with self.assertRaises(IntegrityError):
759
TransactionMiddleware().process_response(self.request, None)
760
self.assertFalse(transaction.is_dirty())
761
self.assertEqual(Band.objects.count(), 0)
762
self.assertFalse(transaction.is_managed())
764
del connections[DEFAULT_DB_ALIAS].commit