diff --git a/libpathod/app.py b/libpathod/app.py index 1a54f7122..1910e80e1 100644 --- a/libpathod/app.py +++ b/libpathod/app.py @@ -4,6 +4,8 @@ import version, language, utils from netlib import http_uastrings logging.basicConfig(level="DEBUG") + + def make_app(noapi): app = Flask(__name__) @@ -14,20 +16,17 @@ def make_app(noapi): version = version.IVERSION ) - @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" - def render(s, cacheable, **kwargs): kwargs["noapi"] = app.config["pathod"].noapi kwargs["nocraft"] = app.config["pathod"].nocraft @@ -37,30 +36,25 @@ def make_app(noapi): resp.headers["Cache-control"] = "public, max-age=4320" return resp - @app.route('/') @app.route('/index.html') def index(): return render("index.html", True, section="main") - @app.route('/download') @app.route('/download.html') def download(): return render("download.html", True, section="download", version=version.VERSION) - @app.route('/about') @app.route('/about.html') def about(): return render("about.html", True, section="about") - @app.route('/docs/pathod') def docs_pathod(): return render("docs_pathod.html", True, section="docs", subsection="pathod") - @app.route('/docs/language') def docs_language(): return render( @@ -69,29 +63,24 @@ def make_app(noapi): subsection="lang" ) - @app.route('/docs/pathoc') def docs_pathoc(): return render("docs_pathoc.html", True, section="docs", subsection="pathoc") - @app.route('/docs/libpathod') def docs_libpathod(): return render("docs_libpathod.html", True, section="docs", subsection="libpathod") - @app.route('/docs/test') def docs_test(): return render("docs_test.html", True, section="docs", subsection="test") - @app.route('/log') def log(): if app.config["pathod"].noapi: abort(404) return render("log.html", False, section="log", log=app.config["pathod"].get_log()) - @app.route('/log/') def onelog(lid): item = app.config["pathod"].log_by_id(int(lid)) @@ -100,7 +89,6 @@ def make_app(noapi): l = pprint.pformat(item) return render("onelog.html", False, section="log", alog=l, lid=lid) - def _preview(is_request): if is_request: template = "request_preview.html" @@ -121,7 +109,7 @@ def make_app(noapi): try: if is_request: - r = language.parse_request(spec) + r = language.parse_requests(spec)[0] else: r = language.parse_response(spec) except language.ParseException, v: @@ -144,14 +132,11 @@ def make_app(noapi): args["output"] = utils.escape_unprintables(s.getvalue()) return render(template, False, **args) - @app.route('/response_preview') def response_preview(): return _preview(False) - @app.route('/request_preview') def request_preview(): return _preview(True) return app - diff --git a/libpathod/cmdline.py b/libpathod/cmdline.py index 1a000a93f..affc40157 100644 --- a/libpathod/cmdline.py +++ b/libpathod/cmdline.py @@ -155,14 +155,12 @@ def go_pathoc(): data = open(r).read() r = data try: - req = language.parse_request(r) + reqs.extend(language.parse_requests(r)) except language.ParseException, v: print >> sys.stderr, "Error parsing request spec: %s"%v.msg print >> sys.stderr, v.marked() sys.exit(1) - reqs.append(req) args.request = reqs - pathoc.main(args) diff --git a/libpathod/language.py b/libpathod/language.py index b4b591675..f40499f6e 100644 --- a/libpathod/language.py +++ b/libpathod/language.py @@ -1030,7 +1030,7 @@ def parse_response(s): raise ParseException(v.msg, v.line, v.col) -def parse_request(s): +def parse_requests(s): """ May raise ParseException """ @@ -1039,6 +1039,11 @@ def parse_request(s): except UnicodeError: raise ParseException("Spec must be valid ASCII.", 0, 0) try: - return Request(Request.expr().parseString(s, parseAll=True)) + parts = pp.OneOrMore( + pp.Group( + Request.expr() + ) + ).parseString(s, parseAll=True) + return [Request(i) for i in parts] except pp.ParseException, v: raise ParseException(v.msg, v.line, v.col) diff --git a/libpathod/pathoc.py b/libpathod/pathoc.py index ae1e98cf4..b9b202eb4 100644 --- a/libpathod/pathoc.py +++ b/libpathod/pathoc.py @@ -18,8 +18,17 @@ class SSLInfo: class Response: - def __init__(self, httpversion, status_code, msg, headers, content, sslinfo): - self.httpversion, self.status_code, self.msg = httpversion, status_code, msg + def __init__( + self, + httpversion, + status_code, + msg, + headers, + content, + sslinfo + ): + self.httpversion, self.status_code = httpversion, status_code + self.msg = msg self.headers, self.content = headers, content self.sslinfo = sslinfo @@ -91,7 +100,7 @@ class Pathoc(tcp.TCPClient): May raise language.ParseException, netlib.http.HttpError or language.FileAccessDenied. """ - r = language.parse_request(spec) + r = language.parse_requests(spec)[0] language.serve(r, self.wfile, self.settings, self.address.host) self.wfile.flush() ret = list(http.read_response(self.rfile, r.method.string(), None)) diff --git a/test/test_language.py b/test/test_language.py index 18c68caa4..007eb5b78 100644 --- a/test/test_language.py +++ b/test/test_language.py @@ -6,6 +6,10 @@ import tutils language.TESTING = True +def parse_request(s): + return language.parse_requests(s)[0] + + class TestValueNakedLiteral: def test_expr(self): v = language.ValueNakedLiteral("foo") @@ -302,8 +306,8 @@ class TestHeaders: assert language.parse_response("400:c'foo'").headers[0].key.val == "Content-Type" assert language.parse_response("400:l'foo'").headers[0].key.val == "Location" - assert 'Android' in language.parse_request("get:/:ua").headers[0].value.val - assert language.parse_request("get:/:ua").headers[0].key.val == "User-Agent" + assert 'Android' in parse_request("get:/:ua").headers[0].value.val + assert parse_request("get:/:ua").headers[0].key.val == "User-Agent" class TestShortcutUserAgent: @@ -337,7 +341,7 @@ class Test_Action: assert l[0].offset == 0 def test_resolve(self): - r = language.parse_request('GET:"/foo"') + r = parse_request('GET:"/foo"') e = language.DisconnectAt("r") ret = e.resolve(r, {}) assert isinstance(ret.offset, int) @@ -446,23 +450,49 @@ class TestPauses: class TestRequest: def test_nonascii(self): - tutils.raises("ascii", language.parse_request, "get:\xf0") + tutils.raises("ascii", parse_request, "get:\xf0") def test_err(self): - tutils.raises(language.ParseException, language.parse_request, 'GET') + tutils.raises(language.ParseException, parse_request, 'GET') def test_simple(self): - r = language.parse_request('GET:"/foo"') + r = parse_request('GET:"/foo"') assert r.method.string() == "GET" assert r.path.string() == "/foo" - r = language.parse_request('GET:/foo') + r = parse_request('GET:/foo') assert r.path.string() == "/foo" - r = language.parse_request('GET:@1k') + r = parse_request('GET:@1k') assert len(r.path.string()) == 1024 + def test_multi(self): + r = language.parse_requests("GET:/ PUT:/") + assert r[0].method.string() == "GET" + assert r[1].method.string() == "PUT" + assert len(r) == 2 + + l = """ + GET + "/foo" + ir,@1 + + PUT + + "/foo + + + + bar" + + ir,@1 + """ + r = language.parse_requests(l) + assert len(r) == 2 + assert r[0].method.string() == "GET" + assert r[1].method.string() == "PUT" + def test_render(self): s = cStringIO.StringIO() - r = language.parse_request("GET:'/foo'") + r = parse_request("GET:'/foo'") assert language.serve(r, s, {}, "foo.com") def test_multiline(self): @@ -471,7 +501,7 @@ class TestRequest: "/foo" ir,@1 """ - r = language.parse_request(l) + r = parse_request(l) assert r.method.string() == "GET" assert r.path.string() == "/foo" assert r.actions @@ -487,24 +517,24 @@ class TestRequest: ir,@1 """ - r = language.parse_request(l) + r = parse_request(l) assert r.method.string() == "GET" assert r.path.string().endswith("bar") assert r.actions def test_spec(self): def rt(s): - s = language.parse_request(s).spec() - assert language.parse_request(s).spec() == s + s = parse_request(s).spec() + assert parse_request(s).spec() == s rt("get:/foo") rt("get:/foo:da") def test_freeze(self): - r = language.parse_request("GET:/:b@100").freeze({}) + r = parse_request("GET:/:b@100").freeze({}) assert len(r.spec()) > 100 def test_path_generator(self): - r = language.parse_request("GET:@100").freeze({}) + r = parse_request("GET:@100").freeze({}) assert len(r.spec()) > 100 diff --git a/test/test_pathoc.py b/test/test_pathoc.py index 88479b6c9..2542b622c 100644 --- a/test/test_pathoc.py +++ b/test/test_pathoc.py @@ -60,7 +60,7 @@ class _TestDaemon: s = cStringIO.StringIO() for i in requests: c.print_request( - language.parse_request(i), + language.parse_requests(i)[0], showreq = showreq, showresp = showresp, explain = explain,