Browse Source

Quote filenames in Location header on redirect

When we redirect the user to the "correct" file name this name should
end up quoted in the header, else we would end up in an infinite
redirect loop.
fix-weird-encoding-problem-in-tests
Sebastian Lohff 1 year ago
parent
commit
9fa4ed0026
  1. 2
      ChangeLog
  2. 2
      servefile/servefile.py
  3. 25
      tests/test_servefile.py

2
ChangeLog

@ -11,6 +11,8 @@ Unreleased @@ -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

2
servefile/servefile.py

@ -60,7 +60,7 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler): @@ -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

25
tests/test_servefile.py

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import io
import os
import pytest
@ -14,9 +15,11 @@ import urllib3 @@ -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): @@ -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): @@ -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): @@ -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): @@ -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)

Loading…
Cancel
Save