Allow specification of multiple patterns from file and on command line

This commit is contained in:
Aldo Cortesi 2014-10-25 16:20:23 +13:00
parent d4e6c25d45
commit 6d8431ab3e
6 changed files with 69 additions and 42 deletions

View File

@ -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/<int:lid>')
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

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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

View File

@ -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,