aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-04-28 17:12:39 +1200
committerAldo Cortesi <aldo@nullcube.com>2012-04-28 17:12:39 +1200
commita779aac9db96b05acb2c4e1b62417bbf37f160f8 (patch)
treec3ef6618b0203db10d9edcea879f8ce817be9244
parent5fc2a63781e554030da9877e8ee56eccc4c873f6 (diff)
downloadmitmproxy-a779aac9db96b05acb2c4e1b62417bbf37f160f8.tar.gz
mitmproxy-a779aac9db96b05acb2c4e1b62417bbf37f160f8.tar.bz2
mitmproxy-a779aac9db96b05acb2c4e1b62417bbf37f160f8.zip
Make specification language more terse, and more regular.
-rw-r--r--libpathod/rparse.py27
-rw-r--r--notes91
-rw-r--r--test/test_rparse.py57
3 files changed, 73 insertions, 102 deletions
diff --git a/libpathod/rparse.py b/libpathod/rparse.py
index 5c6d0257..18d05a69 100644
--- a/libpathod/rparse.py
+++ b/libpathod/rparse.py
@@ -15,6 +15,9 @@ class ParseException(Exception):
def marked(self):
return "%s\n%s"%(self.s, " "*(self.col-1) + "^")
+ def __str__(self):
+ return self.msg
+
class ServerError(Exception): pass
@@ -41,16 +44,17 @@ v_integer = pp.Regex(r"[+-]?\d+")\
.setName("integer")\
.setParseAction(lambda toks: int(toks[0]))
-v_string = pp.MatchFirst(
+
+v_literal = pp.MatchFirst(
[
pp.QuotedString("\"", escChar="\\", unquoteResults=True),
pp.QuotedString("'", escChar="\\", unquoteResults=True),
]
)
-v_literal = pp.MatchFirst(
+v_naked_literal = pp.MatchFirst(
[
- v_string,
+ v_literal,
pp.Word("".join(i for i in pp.printables if i not in ",:"))
]
)
@@ -121,6 +125,13 @@ class ValueLiteral:
return self.val
+class ValueNakedLiteral(ValueLiteral):
+ @classmethod
+ def expr(klass):
+ e = v_naked_literal.copy()
+ return e.setParseAction(lambda x: klass(*x))
+
+
class ValueGenerate:
UNITS = dict(
b = 1024**0,
@@ -163,7 +174,7 @@ class ValueFile:
@classmethod
def expr(klass):
e = pp.Literal("<").suppress()
- e = e + v_literal
+ e = e + v_naked_literal
return e.setParseAction(lambda x: klass(*x))
def get_generator(self, settings):
@@ -197,7 +208,7 @@ class Body:
@classmethod
def expr(klass):
- e = pp.Literal("b:").suppress()
+ e = pp.Literal("b").suppress()
e = e + Value
return e.setParseAction(lambda x: klass(*x))
@@ -208,7 +219,7 @@ class _Pause:
@classmethod
def expr(klass):
- e = pp.Literal("p%s:"%klass.sub).suppress()
+ e = pp.Literal("p%s"%klass.sub).suppress()
e = e + pp.MatchFirst(
[
v_integer,
@@ -273,7 +284,7 @@ class Header:
@classmethod
def expr(klass):
- e = pp.Literal("h:").suppress()
+ e = pp.Literal("h").suppress()
e += Value
e += pp.Literal(":").suppress()
e += Value
@@ -294,7 +305,7 @@ class Code:
def expr(klass):
e = v_integer
e = e + pp.Optional(
- pp.Literal(":").suppress() + Value
+ Value
)
return e.setParseAction(lambda x: klass(*x))
diff --git a/notes b/notes
index 0513cb42..bd315ebe 100644
--- a/notes
+++ b/notes
@@ -1,92 +1,53 @@
-Value Specifiers:
-
- !500k - 500k of random data
- !500k:utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable
- "foo" - literal
- foo - literal
- <path - load from path under data directory
- <"path literal" - load from path under data directory
-
-
Response:
- code:[comma-separated features]
+ code[msg],[comma-separated features]
-Specifying a response:
- Code 200:
- code:msg
- 200:VALUE
-
- Headers:
- h:VALUE:VALUE
-
- Body:
- b:VALUE
-
- Pauses:
- pb:5
- pb:forever
-
- Pause before sending data:
-
- pb:5
-
- Pause after sending data, before hanging up:
-
- pa:5
-
- Pause after sending a random amoutn of data:
+Features:
- pr:5
+ hVALUE:VALUE Set header
+ bVALUE Set body
+ db Disconnect before sending data
+ dr Disconnect randomly
+ pbTIME Pause before sending data for NUM seconds or forever
+ paTIME Pause after sending all data for NUM seconds or forever
+ prTIME Pause randomly for NUM seconds or forever
+ cVALUE Set Content-Type header
+ lVALUE Set Location header
- Disconnect:
-
- Before sending data:
- db
+Time Specifiers:
- Randomly:
+ 5 - 5 seconds
+ 5s - 5 seconds
+ 5m - 5 minutes
+ 5h - 5 hours
- dr
+Value Specifiers:
-Shortcuts:
-
- Redirects:
- code:msg>destination
- code>destination
-
- 301:VALUE>VALUE
- 301>http://foo.bar
-
-
- Content-type:
-
- t:content-type
+ !500k - 500k of random data
+ !500k:utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable
+ "foo" - literal
+ <path - load from path under data directory
+ <"path" - load from path under data directory
Examples:
- 200,b:500k
-
- 404,p:5s,b:1k:printable
-
- 200,t:text/json,p:5s,b:1k
-
- 200,b:1k,xr
-
+ 200,b500k
+ 404,pb5,b1k:printable
+ 200,t"text/json",pr5,b1k
+ 200,b1k,xr
Sequences:
200 * 2 | !forever
-
200 | 404 | 200,b:500g
-
Anchors:
Passed on command-line?
diff --git a/test/test_rparse.py b/test/test_rparse.py
index 8e9da6f0..440803c9 100644
--- a/test/test_rparse.py
+++ b/test/test_rparse.py
@@ -17,7 +17,7 @@ class DummyRequest(StringIO.StringIO):
class uMisc(libpry.AutoTree):
def test_generators(self):
- v = rparse.Value.parseString("val")[0]
+ v = rparse.Value.parseString("'val'")[0]
g = v.get_generator({})
assert g[:] == "val"
@@ -94,26 +94,25 @@ class uMisc(libpry.AutoTree):
assert v.datatype == "digits"
def test_value(self):
- assert rparse.Value.parseString("val")[0].val == "val"
assert rparse.Value.parseString("'val'")[0].val == "val"
assert rparse.Value.parseString('"val"')[0].val == "val"
assert rparse.Value.parseString('"\'val\'"')[0].val == "'val'"
def test_body(self):
e = rparse.Body.expr()
- v = e.parseString("b:foo")[0]
+ v = e.parseString("b'foo'")[0]
assert v.value.val == "foo"
- v = e.parseString("b:!100")[0]
+ v = e.parseString("b!100")[0]
assert str(v.value) == "!100b:bytes"
- v = e.parseString("b:!100g:digits", parseAll=True)[0]
+ v = e.parseString("b!100g:digits", parseAll=True)[0]
assert v.value.datatype == "digits"
assert str(v.value) == "!100g:digits"
def test_header(self):
e = rparse.Header.expr()
- v = e.parseString("h:foo:bar")[0]
+ v = e.parseString("h'foo':'bar'")[0]
assert v.key.val == "foo"
assert v.value.val == "bar"
@@ -122,17 +121,17 @@ class uMisc(libpry.AutoTree):
v = e.parseString("200")[0]
assert v.code == 200
- v = e.parseString("404:msg")[0]
+ v = e.parseString("404'msg'")[0]
assert v.code == 404
assert v.msg.val == "msg"
- r = e.parseString("200:'foo'")[0]
+ r = e.parseString("200'foo'")[0]
assert r.msg.val == "foo"
- r = e.parseString("200:'\"foo\"'")[0]
+ r = e.parseString("200'\"foo\"'")[0]
assert r.msg.val == "\"foo\""
- r = e.parseString('200:"foo"')[0]
+ r = e.parseString('200"foo"')[0]
assert r.msg.val == "foo"
r = e.parseString('404')[0]
@@ -168,20 +167,20 @@ class uDisconnects(libpry.AutoTree):
class uPauses(libpry.AutoTree):
def test_before(self):
e = rparse.PauseBefore.expr()
- v = e.parseString("pb:10")[0]
+ v = e.parseString("pb10")[0]
assert v.value == 10
- v = e.parseString("pb:forever")[0]
+ v = e.parseString("pbforever")[0]
assert v.value == "forever"
def test_after(self):
e = rparse.PauseAfter.expr()
- v = e.parseString("pa:10")[0]
+ v = e.parseString("pa10")[0]
assert v.value == 10
def test_random(self):
e = rparse.PauseRandom.expr()
- v = e.parseString("pr:10")[0]
+ v = e.parseString("pr10")[0]
assert v.value == 10
@@ -191,41 +190,41 @@ class uparse(libpry.AutoTree):
try:
rparse.parse({}, "400:msg,b:")
except rparse.ParseException, v:
- print v.marked()
+ assert v.marked()
def test_parse_header(self):
- r = rparse.parse({}, "400,h:foo:bar")
+ r = rparse.parse({}, '400,h"foo":"bar"')
assert r.get_header("foo") == "bar"
def test_parse_pause_before(self):
- r = rparse.parse({}, "400,pb:10")
+ r = rparse.parse({}, "400,pb10")
assert (0, 10) in r.pauses
def test_parse_pause_after(self):
- r = rparse.parse({}, "400,pa:10")
+ r = rparse.parse({}, "400,pa10")
assert (sys.maxint, 10) in r.pauses
def test_parse_pause_random(self):
- r = rparse.parse({}, "400,pr:10")
+ r = rparse.parse({}, "400,pr10")
assert ("random", 10) in r.pauses
class uResponse(libpry.AutoTree):
def dummy_response(self):
- return rparse.parse({}, "400:msg")
+ return rparse.parse({}, "400'msg'")
def test_response(self):
- r = rparse.parse({}, "400:msg")
+ r = rparse.parse({}, "400'msg'")
assert r.code == 400
assert r.msg == "msg"
- r = rparse.parse({}, "400:msg,b:!100b")
+ r = rparse.parse({}, "400'msg',b!100b")
assert r.msg == "msg"
assert r.body[:]
assert str(r)
def test_ready_randoms(self):
- r = rparse.parse({}, "400:msg")
+ r = rparse.parse({}, "400'msg'")
x = [(0, 5)]
assert r.ready_randoms(100, x) == x
@@ -246,7 +245,7 @@ class uResponse(libpry.AutoTree):
def test_write_values(self):
tst = "foo"*1025
- r = rparse.parse({}, "400:msg")
+ r = rparse.parse({}, "400'msg'")
s = DummyRequest()
r.write_values(s, [tst], [], None)
@@ -254,7 +253,7 @@ class uResponse(libpry.AutoTree):
def test_write_values_pauses(self):
tst = "".join(str(i) for i in range(10))
- r = rparse.parse({}, "400:msg")
+ r = rparse.parse({}, "400'msg'")
for i in range(2, 10):
s = DummyRequest()
@@ -274,7 +273,7 @@ class uResponse(libpry.AutoTree):
def test_render(self):
s = DummyRequest()
- r = rparse.parse({}, "400:msg")
+ r = rparse.parse({}, "400'msg'")
r.render(s)
def test_length(self):
@@ -282,9 +281,9 @@ class uResponse(libpry.AutoTree):
s = DummyRequest()
x.render(s)
assert x.length() == len(s.getvalue())
- testlen(rparse.parse({}, "400:msg"))
- testlen(rparse.parse({}, "400:msg,h:foo:bar"))
- testlen(rparse.parse({}, "400:msg,h:foo:bar,b:!100b"))
+ testlen(rparse.parse({}, "400'msg'"))
+ testlen(rparse.parse({}, "400'msg',h'foo':'bar'"))
+ testlen(rparse.parse({}, "400'msg',h'foo':'bar',b!100b"))
tests = [