Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix bug 1054472: Use ETags to determine if we can send 304s.
Changes the fetch_snippets view to add ETags to outgoing responses that are a hash of their content. It then uses the incoming ETags from clients to determine what snippet content the client currently has cached, and whether new snippet content needs to be delivered or if a 304 can be sent to instruct the client to use their cached snippets. This should allow us to increase the frequency of updates by lowering the amount of data we need to send.
- Loading branch information
Michael Kelly
committed
Aug 22, 2014
1 parent
1dd9014
commit b12f537
Showing
9 changed files
with
289 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,16 @@ | ||
from django.core.urlresolvers import resolve | ||
|
||
from snippets.base.views import fetch_json_snippets, fetch_snippets | ||
|
||
|
||
class FetchSnippetsMiddleware(object): | ||
class SkipMiddleware(object): | ||
""" | ||
If the incoming request is for the fetch_snippets view, execute the view | ||
and return it before other middleware can run. | ||
If the incoming request is for a view that has the skip_middleware | ||
kwarg, execute the view and return the response before other | ||
middleware can run. | ||
fetch_snippets is a very very basic view that doesn't need any of the | ||
middleware that the rest of the site needs, such as the session or csrf | ||
middlewares. To avoid unintended issues (such as headers we don't want | ||
being added to the response) this middleware detects requests to that view | ||
and executes the view early, bypassing the rest of the middleware. | ||
Allows views like the FetchSnippets view to bypass unnecessary | ||
middleware. | ||
""" | ||
def process_request(self, request): | ||
result = resolve(request.path) | ||
if result.func in (fetch_snippets, fetch_json_snippets): | ||
if result.kwargs.pop('skip_middleware', False): | ||
return result.func(request, *result.args, **result.kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,27 @@ | ||
from mock import Mock, patch | ||
from django.test.client import RequestFactory | ||
|
||
from nose.tools import eq_ | ||
|
||
from snippets.base.middleware import FetchSnippetsMiddleware | ||
from snippets.base.middleware import SkipMiddleware | ||
from snippets.base.tests import TestCase | ||
|
||
|
||
class FetchSnippetsMiddlewareTests(TestCase): | ||
def setUp(self): | ||
self.middleware = FetchSnippetsMiddleware() | ||
|
||
@patch('snippets.base.middleware.resolve') | ||
@patch('snippets.base.middleware.fetch_snippets') | ||
def test_resolve_fetch_snippets_match(self, fetch_snippets, resolve): | ||
""" | ||
If resolve returns a match to the fetch_snippets view, return the | ||
result of the view. | ||
""" | ||
request = Mock() | ||
result = resolve.return_value | ||
result.func = fetch_snippets | ||
result.args = (1, 'asdf') | ||
result.kwargs = {'blah': 5} | ||
|
||
eq_(self.middleware.process_request(request), | ||
fetch_snippets.return_value) | ||
fetch_snippets.assert_called_with(request, 1, 'asdf', blah=5) | ||
class SkipMiddlewareTests(TestCase): | ||
urls = 'snippets.base.tests.urls' | ||
|
||
@patch('snippets.base.middleware.resolve') | ||
@patch('snippets.base.middleware.fetch_json_snippets') | ||
def test_resolve_fetch_json_snippets_match(self, fetch_json_snippets, resolve): | ||
""" | ||
If resolve returns a match to the fetch_json_snippets view, | ||
return the result of the view. | ||
""" | ||
request = Mock() | ||
result = resolve.return_value | ||
result.func = fetch_json_snippets | ||
result.args = (1, 'asdf') | ||
result.kwargs = {'blah': 5} | ||
def setUp(self): | ||
self.middleware = SkipMiddleware() | ||
self.factory = RequestFactory() | ||
|
||
eq_(self.middleware.process_request(request), | ||
fetch_json_snippets.return_value) | ||
fetch_json_snippets.assert_called_with(request, 1, 'asdf', blah=5) | ||
def test_process_request_no_kwargs(self): | ||
"""If the skip_middleware kwarg is missing, return None.""" | ||
request = self.factory.get('test') | ||
eq_(self.middleware.process_request(request), None) | ||
|
||
@patch('snippets.base.middleware.resolve') | ||
@patch('snippets.base.middleware.fetch_snippets') | ||
def test_resolve_no_match(self, fetch_snippets, resolve): | ||
def test_process_request_kwargs(self): | ||
""" | ||
If resolve doesn't return a match to the fetch_snippets view, return | ||
None. | ||
If the skip_middleware kwarg is present, execute the view and | ||
return the response. | ||
""" | ||
request = Mock() | ||
result = resolve.return_value | ||
result.func = lambda request: 'asdf' | ||
|
||
eq_(self.middleware.process_request(request), None) | ||
request = self.factory.get('test_skip') | ||
eq_(self.middleware.process_request(request), 'skipped') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from django.conf.urls.defaults import patterns, url | ||
|
||
|
||
def test_view(request): | ||
return 'test' | ||
|
||
|
||
def test_view_skip_middleware(request): | ||
return 'skipped' | ||
|
||
|
||
urlpatterns = patterns('', | ||
url(r'^test$', test_view), | ||
url(r'^test_skip$', test_view_skip_middleware, {'skip_middleware': True}), | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.