Refs #32 - Respect 'attachment' argument in X-Accel optimization.

This commit is contained in:
Benoît Bryon 2013-05-06 16:50:47 +02:00
parent eff185b858
commit e8266615ed
7 changed files with 76 additions and 8 deletions

View file

@ -31,20 +31,29 @@ class DownloadTestCase(TestCase):
self.assertEquals(response['Content-Type'],
'text/plain; charset=utf-8')
self.assertFalse('ContentEncoding' in response)
self.assertEquals(response['Content-Disposition'],
'attachment; filename=hello-world.txt')
if is_attachment:
self.assertEquals(response['Content-Disposition'],
'attachment; filename=hello-world.txt')
else:
self.assertFalse('Content-Disposition' in response)
self.assertEqual(open(self.files['hello-world.txt']).read(),
''.join(response.streaming_content))
class PathDownloadViewTestCase(DownloadTestCase):
"""Test "hello_world" view."""
"""Test "hello_world" and "hello_world_inline" views."""
def test_download_hello_world(self):
"""hello_world view returns hello-world.txt as attachement."""
download_url = reverse('hello_world')
response = self.client.get(download_url)
self.assertDownloadHelloWorld(response)
def test_download_hello_world_inline(self):
"""hello_world view returns hello-world.txt as attachement."""
download_url = reverse('hello_world_inline')
response = self.client.get(download_url)
self.assertDownloadHelloWorld(response, is_attachment=False)
class CustomPathDownloadViewTestCase(DownloadTestCase):
"""Test "fixture_from_path" view."""

View file

@ -17,6 +17,9 @@ urlpatterns = patterns(
url(r'^hello-world\.txt$',
'download_hello_world',
name='hello_world'),
url(r'^hello-world-inline\.txt$',
'download_hello_world_inline',
name='hello_world_inline'),
url(r'^path/(?P<path>[a-zA-Z0-9_-]+\.[a-zA-Z0-9]{1,4})$',
'download_fixture_from_path',
name='fixture_from_path'),

View file

@ -31,6 +31,11 @@ fixtures_storage = FileSystemStorage(location=fixtures_dir)
download_document = views.ObjectDownloadView.as_view(model=Document)
#: Same as download_document, but streamed inline, i.e. not as attachments.
download_document_inline = views.ObjectDownloadView.as_view(model=Document,
attachment=False)
#: Pre-configured view using a storage.
download_fixture_from_storage = views.StorageDownloadView.as_view(
storage=fixtures_storage)
@ -42,6 +47,12 @@ download_fixture_from_storage = views.StorageDownloadView.as_view(
download_hello_world = views.PathDownloadView.as_view(path=hello_world_path)
#: Direct download of one file, based on an absolute path, not as attachment.
download_hello_world_inline = views.PathDownloadView.as_view(
path=hello_world_path,
attachment=False)
class CustomPathDownloadView(views.PathDownloadView):
"""Example of customized PathDownloadView."""
def get_path(self):

View file

@ -37,3 +37,26 @@ class XAccelRedirectDecoratorTestCase(DownloadTestCase):
self.assertFalse('ContentEncoding' in response)
self.assertEquals(response['Content-Disposition'],
'attachment; filename=hello-world.txt')
class InlineXAccelRedirectTestCase(DownloadTestCase):
@temporary_media_root()
def test_response(self):
"""X-Accel optimization respects ``attachment`` attribute."""
document = Document.objects.create(
slug='hello-world',
file=File(open(self.files['hello-world.txt'])),
)
download_url = reverse('download_document_nginx_inline',
kwargs={'slug': 'hello-world'})
response = self.client.get(download_url)
assert_x_accel_redirect(
self,
response,
content_type="text/plain; charset=utf-8",
charset="utf-8",
attachment=False,
redirect_url="/download-optimized/document/hello-world.txt",
expires=None,
with_buffering=None,
limit_rate=None)

View file

@ -2,7 +2,11 @@
from django.conf.urls import patterns, url
urlpatterns = patterns('demoproject.nginx.views',
urlpatterns = patterns(
'demoproject.nginx.views',
url(r'^document-nginx/(?P<slug>[a-zA-Z0-9_-]+)/$',
'download_document_nginx', name='download_document_nginx'),
url(r'^document-nginx-inline/(?P<slug>[a-zA-Z0-9_-]+)/$',
'download_document_nginx_inline',
name='download_document_nginx_inline'),
)

View file

@ -1,4 +1,6 @@
"""Views."""
from django.conf import settings
from django_downloadview.nginx import x_accel_redirect
from demoproject.download import views
@ -8,3 +10,9 @@ download_document_nginx = x_accel_redirect(
views.download_document,
source_dir='/var/www/files',
destination_url='/download-optimized')
download_document_nginx_inline = x_accel_redirect(
views.download_document_inline,
source_dir=settings.MEDIA_ROOT,
destination_url='/download-optimized')

View file

@ -103,11 +103,13 @@ if not hasattr(settings, 'NGINX_DOWNLOAD_MIDDLEWARE_DESTINATION_URL'):
class XAccelRedirectResponse(HttpResponse):
"""Http response that delegates serving file to Nginx."""
def __init__(self, redirect_url, content_type, basename=None, expires=None,
with_buffering=None, limit_rate=None):
with_buffering=None, limit_rate=None, attachment=True):
"""Return a HttpResponse with headers for Nginx X-Accel-Redirect."""
super(XAccelRedirectResponse, self).__init__(content_type=content_type)
self.basename = basename or redirect_url.split('/')[-1]
self['Content-Disposition'] = 'attachment; filename=%s' % self.basename
if attachment:
self.basename = basename or redirect_url.split('/')[-1]
self['Content-Disposition'] = 'attachment; filename={name}'.format(
name=self.basename)
self['X-Accel-Redirect'] = redirect_url
self['X-Accel-Charset'] = content_type_to_charset(content_type)
if with_buffering is not None:
@ -203,6 +205,13 @@ class XAccelRedirectValidator(object):
else:
test_case.assertEqual(header, value)
def assert_attachment(self, test_case, response, value):
header = 'Content-Disposition'
if value:
test_case.assertTrue(response[header].startswith('attachment'))
else:
test_case.assertFalse(header in response)
def assert_x_accel_redirect(test_case, response, **assertions):
"""Make ``test_case`` assert that ``response`` is a XAccelRedirectResponse.
@ -345,7 +354,8 @@ class BaseXAccelRedirectMiddleware(BaseDownloadMiddleware):
basename=response.basename,
expires=expires,
with_buffering=self.with_buffering,
limit_rate=self.limit_rate)
limit_rate=self.limit_rate,
attachment=response.attachment)
class XAccelRedirectMiddleware(BaseXAccelRedirectMiddleware):