mirror of
https://github.com/jazzband/django-downloadview.git
synced 2026-03-16 22:40:25 +00:00
Allow XResponses to keep original headers provided to base response
This commit is contained in:
parent
ba6be8c3cd
commit
51deef0a7e
17 changed files with 130 additions and 10 deletions
|
|
@ -43,3 +43,19 @@ class OptimizedByDecoratorTestCase(django.test.TestCase):
|
||||||
basename="hello-world.txt",
|
basename="hello-world.txt",
|
||||||
file_path="/apache-optimized-by-decorator/hello-world.txt",
|
file_path="/apache-optimized-by-decorator/hello-world.txt",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ModifiedHeadersTestCase(django.test.TestCase):
|
||||||
|
def test_response(self):
|
||||||
|
"""'apache:modified_headers' returns X-Sendfile response."""
|
||||||
|
setup_file()
|
||||||
|
url = reverse("apache:modified_headers")
|
||||||
|
response = self.client.get(url)
|
||||||
|
assert_x_sendfile(
|
||||||
|
self,
|
||||||
|
response,
|
||||||
|
content_type="text/plain; charset=utf-8",
|
||||||
|
basename="hello-world.txt",
|
||||||
|
file_path="/apache-modified-headers/hello-world.txt",
|
||||||
|
)
|
||||||
|
self.assertEqual(response['X-Test'], 'header')
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,9 @@ urlpatterns = [
|
||||||
views.optimized_by_decorator,
|
views.optimized_by_decorator,
|
||||||
name="optimized_by_decorator",
|
name="optimized_by_decorator",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"modified_headers/",
|
||||||
|
views.modified_headers,
|
||||||
|
name="modified_headers",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,17 @@ optimized_by_decorator = x_sendfile(
|
||||||
source_url=storage.base_url,
|
source_url=storage.base_url,
|
||||||
destination_dir="/apache-optimized-by-decorator/",
|
destination_dir="/apache-optimized-by-decorator/",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _modified_headers(request):
|
||||||
|
view = StorageDownloadView.as_view(storage=storage, path="hello-world.txt")
|
||||||
|
response = view(request)
|
||||||
|
response["X-Test"] = 'header'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
modified_headers = x_sendfile(
|
||||||
|
_modified_headers,
|
||||||
|
source_url=storage.base_url,
|
||||||
|
destination_dir="/apache-modified-headers/",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,19 @@ class OptimizedByDecoratorTestCase(django.test.TestCase):
|
||||||
basename="hello-world.txt",
|
basename="hello-world.txt",
|
||||||
file_path="/lighttpd-optimized-by-decorator/hello-world.txt",
|
file_path="/lighttpd-optimized-by-decorator/hello-world.txt",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ModifiedHeadersTestCase(django.test.TestCase):
|
||||||
|
def test_response(self):
|
||||||
|
"""'lighttpd:modified_headers' returns X-Sendfile response."""
|
||||||
|
setup_file()
|
||||||
|
url = reverse("lighttpd:modified_headers")
|
||||||
|
response = self.client.get(url)
|
||||||
|
assert_x_sendfile(
|
||||||
|
self,
|
||||||
|
response,
|
||||||
|
content_type="text/plain; charset=utf-8",
|
||||||
|
basename="hello-world.txt",
|
||||||
|
file_path="/lighttpd-modified-headers/hello-world.txt",
|
||||||
|
)
|
||||||
|
self.assertEqual(response['X-Test'], 'header')
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,9 @@ urlpatterns = [
|
||||||
views.optimized_by_decorator,
|
views.optimized_by_decorator,
|
||||||
name="optimized_by_decorator",
|
name="optimized_by_decorator",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"modified_headers/",
|
||||||
|
views.modified_headers,
|
||||||
|
name="modified_headers",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,17 @@ optimized_by_decorator = x_sendfile(
|
||||||
source_url=storage.base_url,
|
source_url=storage.base_url,
|
||||||
destination_dir="/lighttpd-optimized-by-decorator/",
|
destination_dir="/lighttpd-optimized-by-decorator/",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _modified_headers(request):
|
||||||
|
view = StorageDownloadView.as_view(storage=storage, path="hello-world.txt")
|
||||||
|
response = view(request)
|
||||||
|
response["X-Test"] = 'header'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
modified_headers = x_sendfile(
|
||||||
|
_modified_headers,
|
||||||
|
source_url=storage.base_url,
|
||||||
|
destination_dir="/lighttpd-modified-headers/",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -51,3 +51,23 @@ class OptimizedByDecoratorTestCase(django.test.TestCase):
|
||||||
with_buffering=None,
|
with_buffering=None,
|
||||||
limit_rate=None,
|
limit_rate=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ModifiedHeadersTestCase(django.test.TestCase):
|
||||||
|
def test_response(self):
|
||||||
|
"""'nginx:modified_headers' returns X-Sendfile response."""
|
||||||
|
setup_file()
|
||||||
|
url = reverse("nginx:modified_headers")
|
||||||
|
response = self.client.get(url)
|
||||||
|
assert_x_accel_redirect(
|
||||||
|
self,
|
||||||
|
response,
|
||||||
|
content_type="text/plain; charset=utf-8",
|
||||||
|
charset="utf-8",
|
||||||
|
basename="hello-world.txt",
|
||||||
|
redirect_url="/nginx-modified-headers/hello-world.txt",
|
||||||
|
expires=None,
|
||||||
|
with_buffering=None,
|
||||||
|
limit_rate=None,
|
||||||
|
)
|
||||||
|
self.assertEqual(response['X-Test'], 'header')
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,9 @@ urlpatterns = [
|
||||||
views.optimized_by_decorator,
|
views.optimized_by_decorator,
|
||||||
name="optimized_by_decorator",
|
name="optimized_by_decorator",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"modified_headers/",
|
||||||
|
views.modified_headers,
|
||||||
|
name="modified_headers",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,17 @@ optimized_by_decorator = x_accel_redirect(
|
||||||
source_url=storage.base_url,
|
source_url=storage.base_url,
|
||||||
destination_url="/nginx-optimized-by-decorator/",
|
destination_url="/nginx-optimized-by-decorator/",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _modified_headers(request):
|
||||||
|
view = StorageDownloadView.as_view(storage=storage, path="hello-world.txt")
|
||||||
|
response = view(request)
|
||||||
|
response["X-Test"] = 'header'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
modified_headers = x_accel_redirect(
|
||||||
|
_modified_headers,
|
||||||
|
source_url=storage.base_url,
|
||||||
|
destination_url="/nginx-modified-headers/",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,5 @@ class XSendfileMiddleware(ProxiedDownloadMiddleware):
|
||||||
content_type=response["Content-Type"],
|
content_type=response["Content-Type"],
|
||||||
basename=response.basename,
|
basename=response.basename,
|
||||||
attachment=response.attachment,
|
attachment=response.attachment,
|
||||||
|
headers=response.headers,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ from django_downloadview.response import ProxiedDownloadResponse, content_dispos
|
||||||
class XSendfileResponse(ProxiedDownloadResponse):
|
class XSendfileResponse(ProxiedDownloadResponse):
|
||||||
"Delegates serving file to Apache via X-Sendfile header."
|
"Delegates serving file to Apache via X-Sendfile header."
|
||||||
|
|
||||||
def __init__(self, file_path, content_type, basename=None, attachment=True):
|
def __init__(self, file_path, content_type, basename=None, attachment=True, headers=None):
|
||||||
"""Return a HttpResponse with headers for Apache X-Sendfile."""
|
"""Return a HttpResponse with headers for Apache X-Sendfile."""
|
||||||
super().__init__(content_type=content_type)
|
# content-type must be provided only as keyword argument to response
|
||||||
|
if headers and content_type:
|
||||||
|
headers.pop('Content-Type', None)
|
||||||
|
super().__init__(content_type=content_type, headers=headers)
|
||||||
if attachment:
|
if attachment:
|
||||||
self.basename = basename or os.path.basename(file_path)
|
self.basename = basename or os.path.basename(file_path)
|
||||||
self["Content-Disposition"] = content_disposition(self.basename)
|
self["Content-Disposition"] = content_disposition(self.basename)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django_downloadview.apache.response import XSendfileResponse
|
from django_downloadview.apache.response import XSendfileResponse
|
||||||
|
|
||||||
|
|
||||||
class XSendfileValidator(object):
|
class XSendfileValidator:
|
||||||
"""Utility class to validate XSendfileResponse instances.
|
"""Utility class to validate XSendfileResponse instances.
|
||||||
|
|
||||||
See also :py:func:`assert_x_sendfile` shortcut function.
|
See also :py:func:`assert_x_sendfile` shortcut function.
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@ class XSendfileMiddleware(ProxiedDownloadMiddleware):
|
||||||
self, get_response=None, source_dir=None, source_url=None, destination_dir=None
|
self, get_response=None, source_dir=None, source_url=None, destination_dir=None
|
||||||
):
|
):
|
||||||
"""Constructor."""
|
"""Constructor."""
|
||||||
super(XSendfileMiddleware, self).__init__(
|
super().__init__(get_response, source_dir, source_url, destination_dir)
|
||||||
get_response, source_dir, source_url, destination_dir
|
|
||||||
)
|
|
||||||
|
|
||||||
def process_download_response(self, request, response):
|
def process_download_response(self, request, response):
|
||||||
"""Replace DownloadResponse instances by XSendfileResponse ones."""
|
"""Replace DownloadResponse instances by XSendfileResponse ones."""
|
||||||
|
|
@ -34,4 +32,5 @@ class XSendfileMiddleware(ProxiedDownloadMiddleware):
|
||||||
content_type=response["Content-Type"],
|
content_type=response["Content-Type"],
|
||||||
basename=response.basename,
|
basename=response.basename,
|
||||||
attachment=response.attachment,
|
attachment=response.attachment,
|
||||||
|
headers=response.headers,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ from django_downloadview.response import ProxiedDownloadResponse, content_dispos
|
||||||
class XSendfileResponse(ProxiedDownloadResponse):
|
class XSendfileResponse(ProxiedDownloadResponse):
|
||||||
"Delegates serving file to Lighttpd via X-Sendfile header."
|
"Delegates serving file to Lighttpd via X-Sendfile header."
|
||||||
|
|
||||||
def __init__(self, file_path, content_type, basename=None, attachment=True):
|
def __init__(self, file_path, content_type, basename=None, attachment=True, headers=None):
|
||||||
"""Return a HttpResponse with headers for Lighttpd X-Sendfile."""
|
"""Return a HttpResponse with headers for Lighttpd X-Sendfile."""
|
||||||
super(XSendfileResponse, self).__init__(content_type=content_type)
|
# content-type must be porvided only as keyword argument to response
|
||||||
|
if headers and content_type:
|
||||||
|
headers.pop('Content-Type', None)
|
||||||
|
super().__init__(content_type=content_type, headers=headers)
|
||||||
if attachment:
|
if attachment:
|
||||||
self.basename = basename or os.path.basename(file_path)
|
self.basename = basename or os.path.basename(file_path)
|
||||||
self["Content-Disposition"] = content_disposition(self.basename)
|
self["Content-Disposition"] = content_disposition(self.basename)
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ class XAccelRedirectMiddleware(ProxiedDownloadMiddleware):
|
||||||
with_buffering=self.with_buffering,
|
with_buffering=self.with_buffering,
|
||||||
limit_rate=self.limit_rate,
|
limit_rate=self.limit_rate,
|
||||||
attachment=response.attachment,
|
attachment=response.attachment,
|
||||||
|
headers=response.headers,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,13 @@ class XAccelRedirectResponse(ProxiedDownloadResponse):
|
||||||
with_buffering=None,
|
with_buffering=None,
|
||||||
limit_rate=None,
|
limit_rate=None,
|
||||||
attachment=True,
|
attachment=True,
|
||||||
|
headers=None,
|
||||||
):
|
):
|
||||||
"""Return a HttpResponse with headers for Nginx X-Accel-Redirect."""
|
"""Return a HttpResponse with headers for Nginx X-Accel-Redirect."""
|
||||||
super(XAccelRedirectResponse, self).__init__(content_type=content_type)
|
# content-type must be porvided only as keyword argument to response
|
||||||
|
if headers and content_type:
|
||||||
|
headers.pop('Content-Type', None)
|
||||||
|
super().__init__(content_type=content_type, headers=headers)
|
||||||
if attachment:
|
if attachment:
|
||||||
self.basename = basename or url_basename(redirect_url, content_type)
|
self.basename = basename or url_basename(redirect_url, content_type)
|
||||||
self["Content-Disposition"] = content_disposition(self.basename)
|
self["Content-Disposition"] = content_disposition(self.basename)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django_downloadview.nginx.response import XAccelRedirectResponse
|
from django_downloadview.nginx.response import XAccelRedirectResponse
|
||||||
|
|
||||||
|
|
||||||
class XAccelRedirectValidator(object):
|
class XAccelRedirectValidator:
|
||||||
"""Utility class to validate XAccelRedirectResponse instances.
|
"""Utility class to validate XAccelRedirectResponse instances.
|
||||||
|
|
||||||
See also :py:func:`assert_x_accel_redirect` shortcut function.
|
See also :py:func:`assert_x_accel_redirect` shortcut function.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue