diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2012-04-29 14:20:27 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2012-04-29 14:20:27 +1200 |
commit | 6d4500c67943d03cf0910256ef9dab46789f366f (patch) | |
tree | 7d2d68047e6241c081560a042d4dcdeaae0dbffe | |
parent | f03ce8107075567ea902b88ace2964ee035d45aa (diff) | |
download | mitmproxy-6d4500c67943d03cf0910256ef9dab46789f366f.tar.gz mitmproxy-6d4500c67943d03cf0910256ef9dab46789f366f.tar.bz2 mitmproxy-6d4500c67943d03cf0910256ef9dab46789f366f.zip |
Regularize language even further
- Unify offset specifcation syntax, so there's now oly one form for specify
pauses and disconnects.
- Use @ instead of ! for content generation. Mildy more convenient in the shell.
-rw-r--r-- | libpathod/rparse.py | 93 | ||||
-rw-r--r-- | notes | 23 | ||||
-rw-r--r-- | test/test_rparse.py | 103 | ||||
-rw-r--r-- | todo | 18 |
4 files changed, 116 insertions, 121 deletions
diff --git a/libpathod/rparse.py b/libpathod/rparse.py index b47681cc..de69e9b9 100644 --- a/libpathod/rparse.py +++ b/libpathod/rparse.py @@ -146,18 +146,18 @@ class ValueGenerate: @classmethod def expr(klass): - e = pp.Literal("!").suppress() + v_integer + e = pp.Literal("@").suppress() + v_integer u = reduce(operator.or_, [pp.Literal(i) for i in klass.UNITS.keys()]) e = e + pp.Optional(u, default=None) - s = pp.Literal("-").suppress() + s = pp.Literal(",").suppress() s += reduce(operator.or_, [pp.Literal(i) for i in DATATYPES.keys()]) e += pp.Optional(s, default="bytes") return e.setParseAction(lambda x: klass(*x)) def __str__(self): - return "!%s%s-%s"%(self.usize, self.unit, self.datatype) + return "@%s%s,%s"%(self.usize, self.unit, self.datatype) class ValueFile: @@ -245,60 +245,50 @@ class Body: return e.setParseAction(lambda x: klass(*x)) -class _Pause: - def __init__(self, value): - self.value = value +class PauseAt: + def __init__(self, seconds, offset): + self.seconds, self.offset = seconds, offset @classmethod def expr(klass): - e = pp.Literal("p%s"%klass.sub).suppress() - e = e + pp.MatchFirst( + e = pp.Literal("p").suppress() + e +=pp.MatchFirst( + [ + v_integer, + pp.Literal("f") + ] + ) + e += pp.Literal(",").suppress() + e += pp.MatchFirst( [ v_integer, - pp.Literal("forever") + pp.Literal("r"), + pp.Literal("a"), ] ) return e.setParseAction(lambda x: klass(*x)) - -class PauseBefore(_Pause): - sub = "b" - def mod_response(self, settings, r): - r.actions.append((0, "pause", self.value)) - - -class PauseAfter(_Pause): - sub = "a" - def mod_response(self, settings, r): - r.actions.append((sys.maxint, "pause", self.value)) - - -class PauseRandom(_Pause): - sub = "r" def mod_response(self, settings, r): - r.actions.append(("random", "pause", self.value)) + r.actions.append((self.offset, "pause", self.seconds)) -class _Disconnect: +class DisconnectAt: def __init__(self, value): self.value = value - @classmethod - def expr(klass): - e = pp.Literal("d%s"%klass.sub) - return e.setParseAction(klass) - - -class DisconnectBefore(_Disconnect): - sub = "b" def mod_response(self, settings, r): - r.actions.append((0, "disconnect")) + r.actions.append((self.value, "disconnect")) - -class DisconnectRandom(_Disconnect): - sub = "r" - def mod_response(self, settings, r): - r.actions.append(("random", "disconnect")) + @classmethod + def expr(klass): + e = pp.Literal("d").suppress() + e = e + pp.MatchFirst( + [ + v_integer, + pp.Literal("r") + ] + ) + return e.setParseAction(lambda x: klass(*x)) class Header: @@ -346,11 +336,8 @@ class Response: comps = ( Body, Header, - PauseBefore, - PauseAfter, - PauseRandom, - DisconnectBefore, - DisconnectRandom, + PauseAt, + DisconnectAt, ShortcutContentType, ShortcutLocation, ) @@ -391,13 +378,15 @@ class Response: l += len(self.body) return l - def ready_randoms(self, l, lst): + def ready_actions(self, l, lst): ret = [] - for k, v in lst: - if k == "random": - ret.append((random.randrange(l), v)) - else: - ret.append((k, v)) + for i in lst: + itms = list(i) + if i[0] == "r": + itms[0] = random.randrange(l) + if i[0] == "a": + itms[0] = l+1 + ret.append(tuple(itms)) ret.sort() return ret @@ -469,7 +458,7 @@ class Response: self.body ]) vals.reverse() - actions = self.ready_randoms(self.length(), self.actions) + actions = self.ready_actions(self.length(), self.actions) actions.reverse() return self.write_values(fp, vals, actions) @@ -6,21 +6,18 @@ Response: Features: - hVALUE=VALUE Set header - bVALUE Set body - db Disconnect before sending data - dr Disconnect randomly - pbNUM|forever Pause before sending data for NUM seconds or forever - paNUM|forever Pause after sending all data for NUM seconds or forever - prNUM|forever Pause randomly for NUM seconds or forever - cVALUE Set Content-Type header - lVALUE Set Location header + hVALUE=VALUE Set header + bVALUE Set body + cVALUE Set Content-Type header + lVALUE Set Location header + dOFF|r Disconnect after OFF bytes, measured from the beginning of the response. + pNUM|f,OFF|r|a Pause for NUM seconds after OFF bytes. Value Specifiers: - !500k - 500k of random data - !500k-utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable + @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 @@ -28,8 +25,8 @@ Value Specifiers: Examples: 200:b500k - 404:pb5:b1k-printable - 200:t"text/json":pr5,b1k + 404:pb5:b1k,printable + 200:t"text/json":pr5:b1k 200:b1k:xr diff --git a/test/test_rparse.py b/test/test_rparse.py index c854b0c6..67fac11e 100644 --- a/test/test_rparse.py +++ b/test/test_rparse.py @@ -82,23 +82,23 @@ class uMisc(libpry.AutoTree): libpry.raises("no static directory", v.get_generator, dict()) def test_generated_value(self): - v = rparse.Value.parseString("!10b")[0] + v = rparse.Value.parseString("@10b")[0] assert v.usize == 10 assert v.unit == "b" assert v.bytes() == 10 - v = rparse.Value.parseString("!10")[0] + v = rparse.Value.parseString("@10")[0] assert v.unit == "b" - v = rparse.Value.parseString("!10k")[0] + v = rparse.Value.parseString("@10k")[0] assert v.bytes() == 10240 - v = rparse.Value.parseString("!10g")[0] + v = rparse.Value.parseString("@10g")[0] assert v.bytes() == 1024**3 * 10 - v = rparse.Value.parseString("!10g-digits")[0] + v = rparse.Value.parseString("@10g,digits")[0] assert v.datatype == "digits" g = v.get_generator({}) assert g[:100] - v = rparse.Value.parseString("!10-digits")[0] + v = rparse.Value.parseString("@10,digits")[0] assert v.unit == "b" assert v.datatype == "digits" @@ -112,12 +112,12 @@ class uMisc(libpry.AutoTree): v = e.parseString("b'foo'")[0] assert v.value.val == "foo" - v = e.parseString("b!100")[0] - assert str(v.value) == "!100b-bytes" + 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" + assert str(v.value) == "@100g,digits" def test_header(self): e = rparse.Header.expr() @@ -157,24 +157,21 @@ class uMisc(libpry.AutoTree): class uDisconnects(libpry.AutoTree): def test_parse(self): - assert (0, "disconnect") in rparse.parse({}, "400:db").actions - assert ("random", "disconnect") in rparse.parse({}, "400:dr").actions + assert (0, "disconnect") in rparse.parse({}, "400:d0").actions + assert ("r", "disconnect") in rparse.parse({}, "400:dr").actions - def test_before(self): - e = rparse.DisconnectBefore.expr() - v = e.parseString("db")[0] - assert isinstance(v, rparse.DisconnectBefore) + def test_at(self): + e = rparse.DisconnectAt.expr() + v = e.parseString("d0")[0] + assert isinstance(v, rparse.DisconnectAt) + assert v.value == 0 - v = e.parseString("db")[0] - assert isinstance(v, rparse.DisconnectBefore) + v = e.parseString("d100")[0] + assert v.value == 100 - def test_random(self): - e = rparse.DisconnectRandom.expr() + e = rparse.DisconnectAt.expr() v = e.parseString("dr")[0] - assert isinstance(v, rparse.DisconnectRandom) - - v = e.parseString("dr")[0] - assert isinstance(v, rparse.DisconnectRandom) + assert v.value == "r" class uShortcuts(libpry.AutoTree): @@ -184,27 +181,27 @@ class uShortcuts(libpry.AutoTree): class uPauses(libpry.AutoTree): - def test_before(self): - e = rparse.PauseBefore.expr() - v = e.parseString("pb10")[0] - assert v.value == 10 + def test_parse(self): + e = rparse.PauseAt.expr() + v = e.parseString("p10,10")[0] + assert v.seconds == 10 + assert v.offset == 10 - v = e.parseString("pbforever")[0] - assert v.value == "forever" + v = e.parseString("pf,10")[0] + assert v.seconds == "f" - def test_after(self): - e = rparse.PauseAfter.expr() - v = e.parseString("pa10")[0] - assert v.value == 10 + v = e.parseString("pf,r")[0] + assert v.offset == "r" - def test_random(self): - e = rparse.PauseRandom.expr() - v = e.parseString("pr10")[0] - assert v.value == 10 + v = e.parseString("pf,a")[0] + assert v.offset == "a" + def test_request(self): + r = rparse.parse({}, '400:p10,10') + assert r.actions[0] == (10, "pause", 10) -class uparse(libpry.AutoTree): +class uparse(libpry.AutoTree): def test_parse_err(self): libpry.raises(rparse.ParseException, rparse.parse, {}, "400:msg,b:") try: @@ -218,16 +215,16 @@ class uparse(libpry.AutoTree): assert r.get_header("foo") == "bar" def test_parse_pause_before(self): - r = rparse.parse({}, "400:pb10") + r = rparse.parse({}, "400:p10,0") assert (0, "pause", 10) in r.actions def test_parse_pause_after(self): - r = rparse.parse({}, "400:pa10") - assert (sys.maxint, "pause", 10) in r.actions + r = rparse.parse({}, "400:p10,a") + assert ("a", "pause", 10) in r.actions def test_parse_pause_random(self): - r = rparse.parse({}, "400:pr10") - assert ("random", "pause", 10) in r.actions + r = rparse.parse({}, "400:p10,r") + assert ("r", "pause", 10) in r.actions class uResponse(libpry.AutoTree): @@ -239,23 +236,27 @@ class uResponse(libpry.AutoTree): 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): + def test_ready_actions(self): r = rparse.parse({}, "400'msg'") x = [(0, 5)] - assert r.ready_randoms(100, x) == x + assert r.ready_actions(100, x) == x - x = [("random", 5)] - ret = r.ready_randoms(100, x) + x = [("r", 5)] + ret = r.ready_actions(100, x) assert 0 <= ret[0][0] < 100 + x = [("a", "pause", 5)] + ret = r.ready_actions(100, x) + assert ret[0][0] > 100 + x = [(1, 5), (0, 5)] - assert r.ready_randoms(100, x) == sorted(x) + assert r.ready_actions(100, x) == sorted(x) def test_write_values_disconnects(self): r = self.dummy_response() @@ -304,7 +305,7 @@ class uResponse(libpry.AutoTree): 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':h'foo'='bar':b@100b")) tests = [ @@ -1,5 +1,13 @@ -- Disconnect or pause at specified byte offset -- Logs -- API - - Logs, log reset, log retrieval - - Anchor management + +0.1: + - Disconnect or pause at specified byte offset + - Logs + - API + - Logs, log reset, log retrieval + - Anchor management + +0.2: + - Shortcuts for cookies, auth + - Various SSL errors (expired certs, etc.) + - Caching + |