From 4ec7b8fc18aa124918096099530d2165dd3f2b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Mon, 5 Jan 2026 14:39:45 +0100 Subject: [PATCH] Fix support for X-Accel-Redirect --- docs/nginx/nginx.conf | 43 ++++++++++++++++++++++++++++++++++ ram/portal/views.py | 7 +++++- ram/ram/local_settings.py.tmpl | 1 + ram/ram/settings.py | 10 ++++++++ ram/ram/views.py | 9 ++++++- 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 docs/nginx/nginx.conf diff --git a/docs/nginx/nginx.conf b/docs/nginx/nginx.conf new file mode 100644 index 0000000..8d79439 --- /dev/null +++ b/docs/nginx/nginx.conf @@ -0,0 +1,43 @@ +server { + listen [::]:443 ssl; + listen 443 ssl; + server_name myhost; + + # ssl_certificate ...; + + add_header X-Xss-Protection "1; mode=block"; + add_header Strict-Transport-Security "max-age=15768000"; + add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()"; + add_header Content-Security-Policy "child-src 'none'; object-src 'none'"; + + client_max_body_size 250M; + error_page 403 404 https://$server_name/404; + + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect http:// https://; + proxy_connect_timeout 1800; + proxy_read_timeout 1800; + proxy_max_temp_file_size 8192m; + } + + # static files + location /static { + root /myroot/ram/storage; + } + + # media files + location ~ ^/media/(images|uploads) { + root /myroot/ram/storage; + } + + # protected filed to be served via X-Accel-Redirect + location /private { + internal; + alias /myroot/ram/storage/media; + } +} diff --git a/ram/portal/views.py b/ram/portal/views.py index 016d809..9530366 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -63,7 +63,12 @@ def get_items_ordering(config="items_ordering"): class Render404(View): def get(self, request, exception): - return render(request, "base.html", {"title": "404 page not found"}) + return render( + request, + "base.html", + {"title": "404 page not found"}, + status=404, + ) class GetData(View): diff --git a/ram/ram/local_settings.py.tmpl b/ram/ram/local_settings.py.tmpl index 79463ff..329fac7 100644 --- a/ram/ram/local_settings.py.tmpl +++ b/ram/ram/local_settings.py.tmpl @@ -34,3 +34,4 @@ ALLOWED_HOSTS = ["127.0.0.1", "myhost"] CSRF_TRUSTED_ORIGINS = ["https://myhost"] STATIC_URL = "static/" MEDIA_URL = "media/" +USE_X_ACCEL_REDIRECT = True diff --git a/ram/ram/settings.py b/ram/ram/settings.py index a4d5da0..c149e47 100644 --- a/ram/ram/settings.py +++ b/ram/ram/settings.py @@ -207,6 +207,16 @@ ROLLING_STOCK_TYPES = [ FEATURED_ITEMS_MAX = 6 # If True, use X-Accel-Redirect (Nginx) +# when using X-Accel-Redirect, we don't serve the file +# directly from Django, but let Nginx handle it +# in Nginx config, we need to map /private/ to +# the actual media files location with internal directive +# eg: +# location /private { +# internal; +# alias /path/to/media; +# } +# make also sure that the entire /media is _not_ mapped directly in Nginx USE_X_ACCEL_REDIRECT = False try: diff --git a/ram/ram/views.py b/ram/ram/views.py index d8ba500..b777f4f 100644 --- a/ram/ram/views.py +++ b/ram/ram/views.py @@ -94,10 +94,17 @@ class DownloadFile(View): if not os.path.exists(file.path): break + # in Nginx config, we need to map /private/ to + # the actual media files location with internal directive + # eg: + # location /private { + # internal; + # alias /path/to/media; + # } if getattr(settings, "USE_X_ACCEL_REDIRECT", False): response = HttpResponse() response["Content-Type"] = "" - response["X-Accel-Redirect"] = file.url + response["X-Accel-Redirect"] = f"/private/{file.name}" else: response = FileResponse( open(file.path, "rb"), as_attachment=True