Compare commits
4 Commits
638668242d
...
1ec1671cb1
Author | SHA1 | Date |
---|---|---|
Sebastian Lohff | 1ec1671cb1 | |
Sebastian Lohff | 0dcd09ac80 | |
Sebastian Lohff | ae1800e157 | |
MasterofJOKers | 08ac08718b |
82
servefile
82
servefile
|
@ -407,9 +407,9 @@ class DirListingHandler(FileBaseHandler):
|
||||||
<table summary="Directory Listing">
|
<table summary="Directory Listing">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="name">Name</th>
|
<th class="name"><a onclick="sort('name');">Name</a></th>
|
||||||
<th class="lastModified">Last Modified</th>
|
<th class="last-modified"><a onclick="sort('last-modified');">Last Modified</a></th>
|
||||||
<th class="size">Size</th>
|
<th class="size"><a onclick="sort('size');">Size</a></th>
|
||||||
<th class="type">Type</th>
|
<th class="type">Type</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -417,6 +417,82 @@ class DirListingHandler(FileBaseHandler):
|
||||||
""" % {'path': os.path.normpath(urllib.unquote(self.path))}
|
""" % {'path': os.path.normpath(urllib.unquote(self.path))}
|
||||||
footer = """</tbody></table></div>
|
footer = """</tbody></table></div>
|
||||||
<div class="footer"><a href="http://seba-geek.de/stuff/servefile/">servefile %(version)s</a></div>
|
<div class="footer"><a href="http://seba-geek.de/stuff/servefile/">servefile %(version)s</a></div>
|
||||||
|
<script>
|
||||||
|
function unhumanize(text){
|
||||||
|
var powers = {'K': 1, 'M': 2, 'G': 3, 'T': 4};
|
||||||
|
var number = parseFloat(text.slice(0, text.length - 1));
|
||||||
|
var unit = text.slice(text.length - 1);
|
||||||
|
return number * Math.pow(1024, powers[unit]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function compare_class(cls, modifier, a, b){
|
||||||
|
var atext = a.getElementsByClassName(cls).item(0).textContent,
|
||||||
|
btext = b.getElementsByClassName(cls).item(0).textContent,
|
||||||
|
atype = a.getElementsByClassName("type").item(0).innerHTML,
|
||||||
|
btype = b.getElementsByClassName("type").item(0).innerHTML;
|
||||||
|
|
||||||
|
// always keep directories on top
|
||||||
|
if (atype !== btype) {
|
||||||
|
if (atype === "Directory")
|
||||||
|
return -1
|
||||||
|
if (btype === "Directory")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cls === "name"){
|
||||||
|
if (atype === "Directory")
|
||||||
|
atext = atext.slice(0, atext.length - 1);
|
||||||
|
|
||||||
|
if (btype === "Directory")
|
||||||
|
btext = btext.slice(0, btext.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cls === "size"){
|
||||||
|
aint = unhumanize(atext);
|
||||||
|
bint = unhumanize(btext);
|
||||||
|
// don't change the order of same-size objects
|
||||||
|
if (aint === bint)
|
||||||
|
return 1;
|
||||||
|
return aint > bint ? modifier : -modifier;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return atext.localeCompare(btext) * modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function move_rows(e, i, a){
|
||||||
|
if (i === a.length - 1)
|
||||||
|
return;
|
||||||
|
var par = e.parentNode,
|
||||||
|
next = e.nextSibling;
|
||||||
|
if (next === a[i+1])
|
||||||
|
return;
|
||||||
|
par.removeChild(a[i+1]);
|
||||||
|
if (next)
|
||||||
|
par.insertBefore(a[i+1], next);
|
||||||
|
else
|
||||||
|
par.appendChild(a[i+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sort(cls){
|
||||||
|
var arr = Array.prototype.slice.call(document.getElementsByTagName("tr"));
|
||||||
|
var e = arr.shift();
|
||||||
|
if (!e.sort_modifier || e.sort_cls !== cls)
|
||||||
|
if (cls === "name")
|
||||||
|
e.sort_modifier = -1;
|
||||||
|
else
|
||||||
|
e.sort_modifier = 1;
|
||||||
|
e.sort_cls = cls;
|
||||||
|
e.sort_modifier = -1 * e.sort_modifier;
|
||||||
|
arr = arr.sort(function (a, b) { return compare_class(cls, e.sort_modifier, a, b); });
|
||||||
|
arr.forEach(move_rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = document.getElementsByTagName("tr").item(0);
|
||||||
|
e.sort_modifier = 1;
|
||||||
|
e.sort_cls = "name";
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>""" % {'version': __version__}
|
</html>""" % {'version': __version__}
|
||||||
content = []
|
content = []
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import io
|
import io
|
||||||
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -51,21 +52,6 @@ def datadir(tmp_path):
|
||||||
return _datadir
|
return _datadir
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
|
||||||
def servefile_simple(run_servefile, datadir):
|
|
||||||
data = "NOOT NOOT"
|
|
||||||
p = datadir({'testfile': data}) / 'testfile'
|
|
||||||
|
|
||||||
run_servefile(str(p))
|
|
||||||
|
|
||||||
return dict(host='localhost', port=8080, protocol='http')
|
|
||||||
|
|
||||||
|
|
||||||
def download_ok(r, expected_data, expected_code=200):
|
|
||||||
assert r.status_code == expected_code
|
|
||||||
assert r.text == expected_data
|
|
||||||
|
|
||||||
|
|
||||||
def make_request(path='/', host='localhost', port=8080, method='get', protocol='http', **kwargs):
|
def make_request(path='/', host='localhost', port=8080, method='get', protocol='http', **kwargs):
|
||||||
url = '{}://{}:{}{}'.format(protocol, host, port, path)
|
url = '{}://{}:{}{}'.format(protocol, host, port, path)
|
||||||
print('Calling {} on {} with {}'.format(method, url, kwargs))
|
print('Calling {} on {} with {}'.format(method, url, kwargs))
|
||||||
|
@ -74,12 +60,15 @@ def make_request(path='/', host='localhost', port=8080, method='get', protocol='
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def check_download(expected_data=None, path='/', status_code=200, **kwargs):
|
def check_download(expected_data=None, path='/', fname=None, status_code=200, **kwargs):
|
||||||
|
if fname is None:
|
||||||
|
fname = os.path.basename(path)
|
||||||
r = make_request(path, **kwargs)
|
r = make_request(path, **kwargs)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert r.text == expected_data
|
assert r.text == expected_data
|
||||||
assert r.headers.get('Content-Type') == 'application/octet-stream'
|
assert r.headers.get('Content-Type') == 'application/octet-stream'
|
||||||
# assert r.headers.get('Content-Disposition') == 'attachment; filename=""'
|
if fname:
|
||||||
|
assert r.headers.get('Content-Disposition') == 'attachment; filename="{}"'.format(fname)
|
||||||
assert r.headers.get('Content-Transfer-Encoding') == 'binary'
|
assert r.headers.get('Content-Transfer-Encoding') == 'binary'
|
||||||
|
|
||||||
return r # for additional tests
|
return r # for additional tests
|
||||||
|
@ -97,6 +86,7 @@ def test_correct_headers(run_servefile, datadir):
|
||||||
data = "NOOT NOOT"
|
data = "NOOT NOOT"
|
||||||
p = datadir({'testfile': data}) / 'testfile'
|
p = datadir({'testfile': data}) / 'testfile'
|
||||||
run_servefile(str(p))
|
run_servefile(str(p))
|
||||||
|
|
||||||
r = make_request()
|
r = make_request()
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert r.headers.get('Content-Type') == 'application/octet-stream'
|
assert r.headers.get('Content-Type') == 'application/octet-stream'
|
||||||
|
@ -107,33 +97,32 @@ def test_correct_headers(run_servefile, datadir):
|
||||||
def test_redirect_and_download(run_servefile, datadir):
|
def test_redirect_and_download(run_servefile, datadir):
|
||||||
data = "NOOT NOOT"
|
data = "NOOT NOOT"
|
||||||
p = datadir({'testfile': data}) / 'testfile'
|
p = datadir({'testfile': data}) / 'testfile'
|
||||||
|
|
||||||
run_servefile(str(p))
|
run_servefile(str(p))
|
||||||
|
|
||||||
|
# redirect
|
||||||
r = make_request(allow_redirects=False)
|
r = make_request(allow_redirects=False)
|
||||||
assert r.status_code == 302
|
assert r.status_code == 302
|
||||||
assert r.headers.get('Location') == '/testfile'
|
assert r.headers.get('Location') == '/testfile'
|
||||||
|
|
||||||
r = requests.get("http://127.0.0.1:8080")
|
# normal download
|
||||||
download_ok(r, data)
|
check_download(data, fname='testfile')
|
||||||
|
|
||||||
|
|
||||||
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'
|
||||||
run_servefile([str(p), '-p', '8081'])
|
run_servefile([str(p), '-p', '8081'])
|
||||||
r = make_request(port=8081)
|
|
||||||
download_ok(r, data)
|
check_download(data, fname='testfile', port=8081)
|
||||||
|
|
||||||
|
|
||||||
def test_big_download(run_servefile, datadir):
|
def test_big_download(run_servefile, datadir):
|
||||||
# test with about 10 mb of data
|
# test with about 10 mb of data
|
||||||
data = "x" * (10 * 1024 ** 2)
|
data = "x" * (10 * 1024 ** 2)
|
||||||
p = datadir({'testfile': data}) / 'testfile'
|
p = datadir({'testfile': data}) / 'testfile'
|
||||||
|
|
||||||
run_servefile(str(p))
|
run_servefile(str(p))
|
||||||
r = make_request()
|
|
||||||
download_ok(r, data)
|
check_download(data, fname='testfile')
|
||||||
|
|
||||||
|
|
||||||
def test_authentication(run_servefile, datadir):
|
def test_authentication(run_servefile, datadir):
|
||||||
|
@ -146,8 +135,7 @@ def test_authentication(run_servefile, datadir):
|
||||||
assert '401 - Unauthorized' in r.text
|
assert '401 - Unauthorized' in r.text
|
||||||
assert r.status_code == 401
|
assert r.status_code == 401
|
||||||
|
|
||||||
r = make_request(auth=('user', 'password'))
|
check_download(data, fname='testfile', auth=('user', 'password'))
|
||||||
download_ok(r, data)
|
|
||||||
|
|
||||||
|
|
||||||
def test_serve_directory(run_servefile, datadir):
|
def test_serve_directory(run_servefile, datadir):
|
||||||
|
@ -244,7 +232,7 @@ def test_tar_mode(run_servefile, datadir):
|
||||||
# test contents of tar file
|
# test contents of tar file
|
||||||
r = make_request()
|
r = make_request()
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
tar = tarfile.open(fileobj=io.BytesIO(r.text.encode()))
|
tar = tarfile.open(fileobj=io.BytesIO(r.content))
|
||||||
assert len(tar.getmembers()) == 3
|
assert len(tar.getmembers()) == 3
|
||||||
assert tar.getmember('foo').isdir()
|
assert tar.getmember('foo').isdir()
|
||||||
for filename, content in d['foo'].items():
|
for filename, content in d['foo'].items():
|
||||||
|
@ -254,7 +242,14 @@ def test_tar_mode(run_servefile, datadir):
|
||||||
|
|
||||||
|
|
||||||
def test_tar_compression(run_servefile, datadir):
|
def test_tar_compression(run_servefile, datadir):
|
||||||
pass
|
d = {'foo': 'blubb'}
|
||||||
|
p = datadir(d)
|
||||||
|
run_servefile(['-c', 'gzip', '-t', str(p / 'foo')])
|
||||||
|
|
||||||
|
r = make_request()
|
||||||
|
assert r.status_code == 200
|
||||||
|
tar = tarfile.open(fileobj=io.BytesIO(r.content), mode='r:gz')
|
||||||
|
assert len(tar.getmembers()) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_https(run_servefile, datadir):
|
def test_https(run_servefile, datadir):
|
||||||
|
|
Loading…
Reference in New Issue