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.
This commit is contained in:
parent
1f451e0f29
commit
9fa4ed0026
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue