Permalink
Browse files

Bug 827373: Add cache-control and expires headers to tabzilla.js.

  • Loading branch information...
1 parent 121191e commit e8cded664b467344089f22fd87f1c6cb4c1c7a1e @pmac pmac committed Jan 9, 2013
View
@@ -0,0 +1,29 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import time
+from functools import wraps
+from hashlib import md5
+
+from django.utils.http import http_date
+
+
+def cache_control_expires(num_hours):
+ """
+ Set the appropriate Cache-Control, Expires, and ETag headers for the given
+ number of hours.
+ """
+ num_seconds = num_hours * 60 * 60
+
+ def decorator(func):
+
+ @wraps(func)
+ def inner(request, *args, **kwargs):
+ response = func(request, *args, **kwargs)
+ response['Cache-Control'] = 'max-age=%d' % num_seconds
+ response['Expires'] = http_date(time.time() + num_seconds)
+ response['ETag'] = '"%s"' % md5(response.content).hexdigest()
+ return response
+ return inner
+ return decorator
@@ -0,0 +1,44 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import time
+from math import floor
+
+from django.test import RequestFactory
+from django.utils.http import parse_http_date
+
+from mozorg.tests import TestCase
+from mozorg.tests import views
+
+
+class ViewDecoratorTests(TestCase):
+ def setUp(self):
+ self.rf = RequestFactory()
+
+ def _test_cache_headers(self, view, hours):
+ """
+ Should have appropriate Cache-Control, Expires, and ETag headers.
+ """
+ test_request = self.rf.get('/hi-there-dude/')
+ resp = view(test_request)
+ num_seconds = hours * 60 * 60
+ self.assertEqual(resp['cache-control'], 'max-age=%d' % num_seconds)
+
+ now_date = floor(time.time())
+ exp_date = parse_http_date(resp['expires'])
+ self.assertAlmostEqual(now_date + num_seconds, exp_date, delta=2)
+
+ self.assertEqual(resp['etag'], views.RESPONSE_ETAG)
+
+ def test_cache_headers_48_hours(self):
+ """
+ Test a view that should be cached for 48 hours.
+ """
+ self._test_cache_headers(views.view_test_48_hrs, 48)
+
+ def test_cache_headers_30_days(self):
+ """
+ Test a view that should be cached for 30 days.
+ """
+ self._test_cache_headers(views.view_test_30_days, 30 * 24)
View
@@ -0,0 +1,21 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from django.http import HttpResponse
+
+from mozorg.decorators import cache_control_expires
+
+
+RESPONSE_CONTENT = 'The Dude abides, man.'
+RESPONSE_ETAG = '"9766cf1452d8b193ef3b608848863a13"'
+
+
+@cache_control_expires(48)
+def view_test_48_hrs(request):
+ return HttpResponse(RESPONSE_CONTENT)
+
+
+@cache_control_expires(24 * 30)
+def view_test_30_days(request):
+ return HttpResponse(RESPONSE_CONTENT)
View
@@ -1,5 +1,10 @@
+from math import floor
+import time
+from hashlib import md5
+
from django.conf import settings
from django.test import Client
+from django.utils.http import parse_http_date
from funfactory.urlresolvers import reverse
from mock import patch
@@ -18,6 +23,21 @@ def test_tabzilla_content_type(self):
resp = self.client.get(reverse('tabzilla'))
self.assertEqual(resp['content-type'], 'text/javascript')
+ def test_cache_headers(self):
+ """
+ Should have appropriate Cache-Control, Expires, and ETag headers.
+ """
+ with self.activate('en-US'):
+ resp = self.client.get(reverse('tabzilla'))
+ self.assertEqual(resp['cache-control'], 'max-age=43200') # 12h
+
+ now_date = floor(time.time())
+ exp_date = parse_http_date(resp['expires'])
+ self.assertAlmostEqual(now_date + 43200, exp_date, delta=2)
+
+ etag = '"%s"' % md5(resp.content).hexdigest()
+ self.assertEqual(resp['etag'], etag)
+
@patch.object(settings, 'DEV_LANGUAGES', ['en-US', 'de'])
@patch.object(settings, 'PROD_LANGUAGES', ['en-US', 'de'])
@@ -26,7 +46,7 @@ def setUp(self):
self.client = Client()
def test_locale_preserved(self):
- """The old tabzilla URL should preserve the locale through redirects."""
+ """The tabzilla URL should preserve the locale through redirects."""
resp = self.client.get('/de/tabzilla/media/js/tabzilla.js')
self.assertEqual(resp.status_code, 301)
self.assertEqual(resp['Location'],
View
@@ -1,6 +1,9 @@
import l10n_utils
+from mozorg.decorators import cache_control_expires
+
+@cache_control_expires(12)
def tabzilla_js(request):
return l10n_utils.render(request, 'tabzilla/tabzilla.js',
content_type='text/javascript')
View
@@ -1,10 +1,5 @@
ExpiresActive on
-# bug 827373
-<Location /*/tabzilla/tabzilla.js>
- ExpiresByType text/javascript "access plus 12 hours"
-</Location>
-
## Redirect things to django!
# bug 821006

0 comments on commit e8cded6

Please sign in to comment.