Skip to content

Commit

Permalink
Merge pull request #212 from sevdog/xaccel-headers
Browse files Browse the repository at this point in the history
Allow XResponses to keep original headers provided to base response
  • Loading branch information
Natim authored Aug 5, 2024
2 parents 71488c4 + 51deef0 commit 1b294f0
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 10 deletions.
16 changes: 16 additions & 0 deletions demo/demoproject/apache/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,19 @@ def test_response(self):
basename="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')
5 changes: 5 additions & 0 deletions demo/demoproject/apache/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@
views.optimized_by_decorator,
name="optimized_by_decorator",
),
path(
"modified_headers/",
views.modified_headers,
name="modified_headers",
),
]
14 changes: 14 additions & 0 deletions demo/demoproject/apache/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@
source_url=storage.base_url,
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/",
)
16 changes: 16 additions & 0 deletions demo/demoproject/lighttpd/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,19 @@ def test_response(self):
basename="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')
5 changes: 5 additions & 0 deletions demo/demoproject/lighttpd/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@
views.optimized_by_decorator,
name="optimized_by_decorator",
),
path(
"modified_headers/",
views.modified_headers,
name="modified_headers",
),
]
14 changes: 14 additions & 0 deletions demo/demoproject/lighttpd/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@
source_url=storage.base_url,
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/",
)
20 changes: 20 additions & 0 deletions demo/demoproject/nginx/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,23 @@ def test_response(self):
with_buffering=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')
5 changes: 5 additions & 0 deletions demo/demoproject/nginx/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@
views.optimized_by_decorator,
name="optimized_by_decorator",
),
path(
"modified_headers/",
views.modified_headers,
name="modified_headers",
),
]
14 changes: 14 additions & 0 deletions demo/demoproject/nginx/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@
source_url=storage.base_url,
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/",
)
1 change: 1 addition & 0 deletions django_downloadview/apache/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ def process_download_response(self, request, response):
content_type=response["Content-Type"],
basename=response.basename,
attachment=response.attachment,
headers=response.headers,
)
7 changes: 5 additions & 2 deletions django_downloadview/apache/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
class XSendfileResponse(ProxiedDownloadResponse):
"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."""
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:
self.basename = basename or os.path.basename(file_path)
self["Content-Disposition"] = content_disposition(self.basename)
Expand Down
2 changes: 1 addition & 1 deletion django_downloadview/apache/tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django_downloadview.apache.response import XSendfileResponse


class XSendfileValidator(object):
class XSendfileValidator:
"""Utility class to validate XSendfileResponse instances.
See also :py:func:`assert_x_sendfile` shortcut function.
Expand Down
5 changes: 2 additions & 3 deletions django_downloadview/lighttpd/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ def __init__(
self, get_response=None, source_dir=None, source_url=None, destination_dir=None
):
"""Constructor."""
super(XSendfileMiddleware, self).__init__(
get_response, source_dir, source_url, destination_dir
)
super().__init__(get_response, source_dir, source_url, destination_dir)

def process_download_response(self, request, response):
"""Replace DownloadResponse instances by XSendfileResponse ones."""
Expand All @@ -34,4 +32,5 @@ def process_download_response(self, request, response):
content_type=response["Content-Type"],
basename=response.basename,
attachment=response.attachment,
headers=response.headers,
)
7 changes: 5 additions & 2 deletions django_downloadview/lighttpd/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
class XSendfileResponse(ProxiedDownloadResponse):
"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."""
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:
self.basename = basename or os.path.basename(file_path)
self["Content-Disposition"] = content_disposition(self.basename)
Expand Down
1 change: 1 addition & 0 deletions django_downloadview/nginx/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def process_download_response(self, request, response):
with_buffering=self.with_buffering,
limit_rate=self.limit_rate,
attachment=response.attachment,
headers=response.headers,
)


Expand Down
6 changes: 5 additions & 1 deletion django_downloadview/nginx/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ def __init__(
with_buffering=None,
limit_rate=None,
attachment=True,
headers=None,
):
"""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:
self.basename = basename or url_basename(redirect_url, content_type)
self["Content-Disposition"] = content_disposition(self.basename)
Expand Down
2 changes: 1 addition & 1 deletion django_downloadview/nginx/tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django_downloadview.nginx.response import XAccelRedirectResponse


class XAccelRedirectValidator(object):
class XAccelRedirectValidator:
"""Utility class to validate XAccelRedirectResponse instances.
See also :py:func:`assert_x_accel_redirect` shortcut function.
Expand Down

0 comments on commit 1b294f0

Please sign in to comment.