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
|
wished the ports can be set from outside by specifying the
|
||||||
environment variables SERVEFILE_DEFAULT_PORT and
|
environment variables SERVEFILE_DEFAULT_PORT and
|
||||||
SERVEFILE_SECONDARY_PORT
|
SERVEFILE_SECONDARY_PORT
|
||||||
|
* fixed broken redirect when filename contained umlauts or other characters
|
||||||
|
that should have been quoted
|
||||||
|
|
||||||
|
|
||||||
2020-10-30 v0.5.1
|
2020-10-30 v0.5.1
|
||||||
|
|
|
@ -60,7 +60,7 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
fileName = self.fileName
|
fileName = self.fileName
|
||||||
if unquote(self.path) != "/" + fileName:
|
if unquote(self.path) != "/" + fileName:
|
||||||
self.send_response(302)
|
self.send_response(302)
|
||||||
self.send_header('Location', '/' + fileName)
|
self.send_header('Location', '/' + quote(fileName))
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -14,9 +15,11 @@ import urllib3
|
||||||
|
|
||||||
if sys.version_info.major >= 3:
|
if sys.version_info.major >= 3:
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from urllib.parse import quote
|
||||||
connrefused_exc = ConnectionRefusedError
|
connrefused_exc = ConnectionRefusedError
|
||||||
else:
|
else:
|
||||||
from pathlib2 import Path
|
from pathlib2 import Path
|
||||||
|
from urllib import quote
|
||||||
connrefused_exc = socket.error
|
connrefused_exc = socket.error
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +84,7 @@ def datadir(tmp_path):
|
||||||
_datadir(v, new_path)
|
_datadir(v, new_path)
|
||||||
else:
|
else:
|
||||||
if hasattr(v, 'decode'):
|
if hasattr(v, 'decode'):
|
||||||
v = v.decode() # python2 compability
|
v = v.decode('utf-8') # python2 compability
|
||||||
(path / k).write_text(v)
|
(path / k).write_text(v)
|
||||||
|
|
||||||
return path
|
return path
|
||||||
|
@ -162,6 +165,23 @@ def test_redirect_and_download(run_servefile, datadir):
|
||||||
check_download(data, fname='testfile')
|
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):
|
def test_specify_port(run_servefile, datadir):
|
||||||
data = "NOOT NOOT"
|
data = "NOOT NOOT"
|
||||||
p = datadir({'testfile': data}) / 'testfile'
|
p = datadir({'testfile': data}) / 'testfile'
|
||||||
|
@ -210,6 +230,7 @@ def test_serve_directory(run_servefile, datadir):
|
||||||
'bar': {'thisisaverylongfilenamefortestingthatthisstillworksproperly': 'jup!'},
|
'bar': {'thisisaverylongfilenamefortestingthatthisstillworksproperly': 'jup!'},
|
||||||
'noot': 'still data in here',
|
'noot': 'still data in here',
|
||||||
'bigfile': 'x' * (10 * 1024 ** 2),
|
'bigfile': 'x' * (10 * 1024 ** 2),
|
||||||
|
'möwe': 'KRAKRAKRAKA',
|
||||||
}
|
}
|
||||||
p = datadir(d)
|
p = datadir(d)
|
||||||
run_servefile([str(p), '-l'])
|
run_servefile([str(p), '-l'])
|
||||||
|
@ -219,7 +240,7 @@ def test_serve_directory(run_servefile, datadir):
|
||||||
for path in '/', '/../':
|
for path in '/', '/../':
|
||||||
r = make_request(path)
|
r = make_request(path)
|
||||||
for k in d:
|
for k in d:
|
||||||
assert k in r.text
|
assert quote(k) in r.text
|
||||||
|
|
||||||
for fname, content in d['foo'].items():
|
for fname, content in d['foo'].items():
|
||||||
check_download(content, '/foo/' + fname)
|
check_download(content, '/foo/' + fname)
|
||||||
|
|
Loading…
Reference in New Issue