aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libpathod/app.py18
-rw-r--r--libpathod/language.py11
-rw-r--r--libpathod/pathod.py6
-rw-r--r--test/test_app.py5
-rw-r--r--test/test_language.py12
-rw-r--r--test/test_pathoc.py1
-rw-r--r--test/test_pathod.py11
-rw-r--r--test/tutils.py2
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
)