diff options
-rw-r--r-- | libpathod/app.py | 18 | ||||
-rw-r--r-- | libpathod/language.py | 11 | ||||
-rw-r--r-- | libpathod/pathod.py | 6 | ||||
-rw-r--r-- | test/test_app.py | 5 | ||||
-rw-r--r-- | test/test_language.py | 12 | ||||
-rw-r--r-- | test/test_pathoc.py | 1 | ||||
-rw-r--r-- | test/test_pathod.py | 11 | ||||
-rw-r--r-- | test/tutils.py | 2 |
8 files changed, 52 insertions, 14 deletions
diff --git a/libpathod/app.py b/libpathod/app.py index fc4e23ec..1ebe9901 100644 --- a/libpathod/app.py +++ b/libpathod/app.py @@ -13,17 +13,17 @@ def api(): ) - @app.route('/api/log') - def api_log(): - return jsonify( - log = app.config["pathod"].get_log() - ) +@app.route('/api/log') +def api_log(): + return jsonify( + log = app.config["pathod"].get_log() + ) - @app.route('/api/clear_log') - def api_clear_log(): - app.config["pathod"].clear_log() - return "OK" +@app.route('/api/clear_log') +def api_clear_log(): + app.config["pathod"].clear_log() + return "OK" def render(s, cacheable, **kwargs): diff --git a/libpathod/language.py b/libpathod/language.py index c9aa7f66..fa80360b 100644 --- a/libpathod/language.py +++ b/libpathod/language.py @@ -428,7 +428,7 @@ class _Action: def __repr__(self): return self.spec() - + def accept(self, settings, r): r.actions.append(self) @@ -665,6 +665,7 @@ class Message: # Careful not to log any VALUE specs without sanitizing them first. We truncate at 1k. if hasattr(v, "__len__"): v = v[:TRUNCATE] + v = v.encode("string_escape") ret[i] = v return ret @@ -815,6 +816,10 @@ def parse_response(settings, s): """ May raise ParseException or FileAccessDenied """ + try: + s.decode("ascii") + except UnicodeError: + raise ParseException("Spec must be valid ASCII.", 0, 0) if s.startswith(FILESTART): s = read_file(settings, s) try: @@ -827,6 +832,10 @@ def parse_request(settings, s): """ May raise ParseException or FileAccessDenied """ + try: + s.decode("ascii") + except UnicodeError: + raise ParseException("Spec must be valid ASCII.", 0, 0) if s.startswith(FILESTART): s = read_file(settings, s) try: diff --git a/libpathod/pathod.py b/libpathod/pathod.py index 9d343a51..d4535d03 100644 --- a/libpathod/pathod.py +++ b/libpathod/pathod.py @@ -1,4 +1,4 @@ -import urllib, threading, re, logging, socket, sys +import urllib, threading, re, logging, socket, sys, base64 from netlib import tcp, http, odict, wsgi import netlib.utils import version, app, language @@ -149,10 +149,10 @@ class PathodHandler(tcp.BaseHandler): again, log = self.handle_request() if log: if self.server.logreq: - log["request_bytes"] = self.rfile.get_log() + log["request_bytes"] = self.rfile.get_log().encode("string_escape") self._log_bytes("Request", log["request_bytes"], self.server.hexdump) if self.server.logresp: - log["response_bytes"] = self.wfile.get_log() + log["response_bytes"] = self.wfile.get_log().encode("string_escape") self._log_bytes("Response", log["response_bytes"], self.server.hexdump) self.server.add_log(log) if not again: diff --git a/test/test_app.py b/test/test_app.py index e7c1c085..7b2451d6 100644 --- a/test/test_app.py +++ b/test/test_app.py @@ -11,10 +11,15 @@ class TestApp(tutils.DaemonTests): r = self.getpath("/about") assert r.ok + def test_download(self): + r = self.getpath("/download") + assert r.ok + def test_docs(self): assert self.getpath("/docs/pathod").status_code == 200 assert self.getpath("/docs/pathoc").status_code == 200 assert self.getpath("/docs/language").status_code == 200 + assert self.getpath("/docs/libpathod").status_code == 200 assert self.getpath("/docs/test").status_code == 200 def test_log(self): diff --git a/test/test_language.py b/test/test_language.py index a0781327..e4da6d4d 100644 --- a/test/test_language.py +++ b/test/test_language.py @@ -226,6 +226,10 @@ class Test_Action: ret = e.resolve_offset(r) assert isinstance(ret.offset, int) + def test_repr(self): + e = language.DisconnectAt("r") + assert repr(e) + class TestDisconnects: def test_parse_response(self): @@ -281,7 +285,7 @@ class TestInject: e = language.InjectAt.expr() v = e.parseString("i0,'foo'")[0] assert v.spec() == 'i0,"foo"' - + class TestPauses: def test_parse_response(self): @@ -322,6 +326,9 @@ class TestParseRequest: r = language.parse_request(d, "+request") assert r.path == "/foo" + def test_nonascii(self): + tutils.raises("ascii", language.parse_request, {}, "get:\xf0") + def test_err(self): tutils.raises(language.ParseException, language.parse_request, {}, 'GET') @@ -381,6 +388,9 @@ class TestParseResponse: assert v.marked() assert str(v) + def test_nonascii(self): + tutils.raises("ascii", language.parse_response, {}, "foo:b\xf0") + def test_parse_header(self): r = language.parse_response({}, '400:h"foo"="bar"') assert utils.get_header("foo", r.headers) diff --git a/test/test_pathoc.py b/test/test_pathoc.py index bec339cb..c22fd4f8 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -52,6 +52,7 @@ class TestDaemon: def test_timeout(self): assert "Timeout" in self.tval(["get:'/p/200:p0,10'"], timeout=0.01) assert "HTTP" in self.tval(["get:'/p/200:p5,10'"], showresp=True, timeout=0.01) + assert not "HTTP" in self.tval(["get:'/p/200:p5,10'"], showresp=True, timeout=0.01, ignoretimeout=True) def test_showresp(self): reqs = [ "get:/api/info:p0,0", "get:/api/info:p0,0" ] diff --git a/test/test_pathod.py b/test/test_pathod.py index 429c2ef9..7bbb5545 100644 --- a/test/test_pathod.py +++ b/test/test_pathod.py @@ -61,7 +61,18 @@ class TestNohang(tutils.DaemonTests): assert "Pauses have been disabled" in l["response"]["error"] +class TestHexdump(tutils.DaemonTests): + hexdump = True + def test_hexdump(self): + r = self.get(r"200:b'\xf0'") + + class CommonTests(tutils.DaemonTests): + def test_binarydata(self): + r = self.get(r"200:b'\xf0'") + l = self.d.last_log() + # FIXME: Other binary data elements + def test_sizelimit(self): r = self.get("200:b@1g") assert r.status_code == 800 diff --git a/test/tutils.py b/test/tutils.py index 71a6034f..a63ed7eb 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -9,6 +9,7 @@ class DaemonTests: nohang = False ssl = False timeout = None + hexdump = False @classmethod def setUpAll(self): self.d = test.Daemon( @@ -20,6 +21,7 @@ class DaemonTests: noapi = self.noapi, nohang = self.nohang, timeout = self.timeout, + hexdump = self.hexdump, logreq = True, logresp = True ) |