diff --git a/ChangeLog b/ChangeLog index e1ad90b..1d8e8b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ Unreleased wished the ports can be set from outside by specifying the environment variables SERVEFILE_DEFAULT_PORT and SERVEFILE_SECONDARY_PORT + * fixed broken redirect when filename contained umlauts or other characters + that should have been quoted 2020-10-30 v0.5.1 diff --git a/servefile/servefile.py b/servefile/servefile.py index 21df9b2..7e7fd48 100755 --- a/servefile/servefile.py +++ b/servefile/servefile.py @@ -60,7 +60,7 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler): fileName = self.fileName if unquote(self.path) != "/" + fileName: self.send_response(302) - self.send_header('Location', '/' + fileName) + self.send_header('Location', '/' + quote(fileName)) self.end_headers() return True return False diff --git a/tests/test_servefile.py b/tests/test_servefile.py index 22d0098..3d0cf61 100644 --- a/tests/test_servefile.py +++ b/tests/test_servefile.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import io import os import pytest @@ -14,9 +15,11 @@ import urllib3 if sys.version_info.major >= 3: from pathlib import Path + from urllib.parse import quote connrefused_exc = ConnectionRefusedError else: from pathlib2 import Path + from urllib import quote connrefused_exc = socket.error @@ -81,7 +84,7 @@ def datadir(tmp_path): _datadir(v, new_path) else: if hasattr(v, 'decode'): - v = v.decode() # python2 compability + v = v.decode('utf-8') # python2 compability (path / k).write_text(v) return path @@ -162,6 +165,23 @@ def test_redirect_and_download(run_servefile, datadir): check_download(data, fname='testfile') +def test_redirect_and_download_with_umlaut(run_servefile, datadir): + data = "NÖÖT NÖÖT" + filename = "tästføile" + p = datadir({filename: data}) / filename + run_servefile(str(p)) + + # redirect + r = make_request(allow_redirects=False) + assert r.status_code == 302 + assert r.headers.get('Location') == '/{}'.format(quote(filename)) + + # normal download + if sys.version_info.major < 3: + data = unicode(data, 'utf-8') + check_download(data, fname=filename) + + def test_specify_port(run_servefile, datadir): data = "NOOT NOOT" p = datadir({'testfile': data}) / 'testfile' @@ -210,6 +230,7 @@ def test_serve_directory(run_servefile, datadir): 'bar': {'thisisaverylongfilenamefortestingthatthisstillworksproperly': 'jup!'}, 'noot': 'still data in here', 'bigfile': 'x' * (10 * 1024 ** 2), + 'möwe': 'KRAKRAKRAKA', } p = datadir(d) run_servefile([str(p), '-l']) @@ -219,7 +240,7 @@ def test_serve_directory(run_servefile, datadir): for path in '/', '/../': r = make_request(path) for k in d: - assert k in r.text + assert quote(k) in r.text for fname, content in d['foo'].items(): check_download(content, '/foo/' + fname)