Skip to content

Commit

Permalink
Merge pull request #5024 from rtfd/humitos/nginx/encode-iri-filepath
Browse files Browse the repository at this point in the history
Convert an IRI path to URI before setting as NGINX header
  • Loading branch information
ericholscher authored Jan 10, 2019
2 parents 8e05713 + adb5218 commit c2391c0
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
10 changes: 9 additions & 1 deletion readthedocs/core/views/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.utils.encoding import iri_to_uri
from django.views.static import serve

from readthedocs.builds.models import Version
Expand Down Expand Up @@ -134,10 +135,17 @@ def _serve_file(request, filename, basepath):
if encoding:
response['Content-Encoding'] = encoding
try:
response['X-Accel-Redirect'] = os.path.join(
iri_path = os.path.join(
basepath[len(settings.SITE_ROOT):],
filename,
)
# NGINX does not support non-ASCII characters in the header, so we
# convert the IRI path to URI so it's compatible with what NGINX expects
# as the header value.
# https://github.com/benoitc/gunicorn/issues/1448
# https://docs.djangoproject.com/en/1.11/ref/unicode/#uri-and-iri-handling
x_accel_redirect = iri_to_uri(iri_path)
response['X-Accel-Redirect'] = x_accel_redirect
except UnicodeEncodeError:
raise Http404

Expand Down
14 changes: 13 additions & 1 deletion readthedocs/rtd_tests/tests/test_doc_serving.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import absolute_import
# -*- coding: utf-8 -*-

from __future__ import absolute_import, unicode_literals, division, print_function
import mock
import django_dynamic_fixture as fixture

Expand Down Expand Up @@ -57,6 +59,16 @@ def test_private_nginx_serving(self):
r._headers['x-accel-redirect'][1], '/private_web_root/private/en/latest/usage.html'
)

@override_settings(PYTHON_MEDIA=False)
def test_private_nginx_serving_unicode_filename(self):
with mock.patch('readthedocs.core.views.serve.os.path.exists', return_value=True):
request = self.request(self.private_url, user=self.eric)
r = _serve_symlink_docs(request, project=self.private, filename='/en/latest/úñíčódé.html', privacy_level='private')
self.assertEqual(r.status_code, 200)
self.assertEqual(
r._headers['x-accel-redirect'][1], '/private_web_root/private/en/latest/%C3%BA%C3%B1%C3%AD%C4%8D%C3%B3d%C3%A9.html'
)

@override_settings(PYTHON_MEDIA=False)
def test_private_files_not_found(self):
request = self.request(self.private_url, user=self.eric)
Expand Down

0 comments on commit c2391c0

Please sign in to comment.