mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-12-02 12:01:17 +00:00
Make specification language more terse, and more regular.
This commit is contained in:
parent
5fc2a63781
commit
a779aac9db
@ -15,6 +15,9 @@ class ParseException(Exception):
|
|||||||
def marked(self):
|
def marked(self):
|
||||||
return "%s\n%s"%(self.s, " "*(self.col-1) + "^")
|
return "%s\n%s"%(self.s, " "*(self.col-1) + "^")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
class ServerError(Exception): pass
|
class ServerError(Exception): pass
|
||||||
|
|
||||||
@ -41,16 +44,17 @@ v_integer = pp.Regex(r"[+-]?\d+")\
|
|||||||
.setName("integer")\
|
.setName("integer")\
|
||||||
.setParseAction(lambda toks: int(toks[0]))
|
.setParseAction(lambda toks: int(toks[0]))
|
||||||
|
|
||||||
v_string = pp.MatchFirst(
|
|
||||||
|
v_literal = pp.MatchFirst(
|
||||||
[
|
[
|
||||||
pp.QuotedString("\"", escChar="\\", unquoteResults=True),
|
pp.QuotedString("\"", escChar="\\", unquoteResults=True),
|
||||||
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 ",:"))
|
pp.Word("".join(i for i in pp.printables if i not in ",:"))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -121,6 +125,13 @@ class ValueLiteral:
|
|||||||
return self.val
|
return self.val
|
||||||
|
|
||||||
|
|
||||||
|
class ValueNakedLiteral(ValueLiteral):
|
||||||
|
@classmethod
|
||||||
|
def expr(klass):
|
||||||
|
e = v_naked_literal.copy()
|
||||||
|
return e.setParseAction(lambda x: klass(*x))
|
||||||
|
|
||||||
|
|
||||||
class ValueGenerate:
|
class ValueGenerate:
|
||||||
UNITS = dict(
|
UNITS = dict(
|
||||||
b = 1024**0,
|
b = 1024**0,
|
||||||
@ -163,7 +174,7 @@ class ValueFile:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("<").suppress()
|
e = pp.Literal("<").suppress()
|
||||||
e = e + v_literal
|
e = e + v_naked_literal
|
||||||
return e.setParseAction(lambda x: klass(*x))
|
return e.setParseAction(lambda x: klass(*x))
|
||||||
|
|
||||||
def get_generator(self, settings):
|
def get_generator(self, settings):
|
||||||
@ -197,7 +208,7 @@ class Body:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("b:").suppress()
|
e = pp.Literal("b").suppress()
|
||||||
e = e + Value
|
e = e + Value
|
||||||
return e.setParseAction(lambda x: klass(*x))
|
return e.setParseAction(lambda x: klass(*x))
|
||||||
|
|
||||||
@ -208,7 +219,7 @@ class _Pause:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("p%s:"%klass.sub).suppress()
|
e = pp.Literal("p%s"%klass.sub).suppress()
|
||||||
e = e + pp.MatchFirst(
|
e = e + pp.MatchFirst(
|
||||||
[
|
[
|
||||||
v_integer,
|
v_integer,
|
||||||
@ -273,7 +284,7 @@ class Header:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("h:").suppress()
|
e = pp.Literal("h").suppress()
|
||||||
e += Value
|
e += Value
|
||||||
e += pp.Literal(":").suppress()
|
e += pp.Literal(":").suppress()
|
||||||
e += Value
|
e += Value
|
||||||
@ -294,7 +305,7 @@ class Code:
|
|||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = v_integer
|
e = v_integer
|
||||||
e = e + pp.Optional(
|
e = e + pp.Optional(
|
||||||
pp.Literal(":").suppress() + Value
|
Value
|
||||||
)
|
)
|
||||||
return e.setParseAction(lambda x: klass(*x))
|
return e.setParseAction(lambda x: klass(*x))
|
||||||
|
|
||||||
|
103
notes
103
notes
@ -1,92 +1,53 @@
|
|||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
code[msg],[comma-separated features]
|
||||||
|
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
Time Specifiers:
|
||||||
|
|
||||||
|
5 - 5 seconds
|
||||||
|
5s - 5 seconds
|
||||||
|
5m - 5 minutes
|
||||||
|
5h - 5 hours
|
||||||
|
|
||||||
|
|
||||||
Value Specifiers:
|
Value Specifiers:
|
||||||
|
|
||||||
!500k - 500k of random data
|
!500k - 500k of random data
|
||||||
!500k:utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable
|
!500k:utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable
|
||||||
"foo" - literal
|
"foo" - literal
|
||||||
foo - literal
|
|
||||||
<path - load from path under data directory
|
<path - load from path under data directory
|
||||||
<"path literal" - load from path under data directory
|
<"path" - load from path under data directory
|
||||||
|
|
||||||
|
|
||||||
Response:
|
|
||||||
|
|
||||||
code:[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:
|
|
||||||
|
|
||||||
pr:5
|
|
||||||
|
|
||||||
|
|
||||||
Disconnect:
|
|
||||||
|
|
||||||
Before sending data:
|
|
||||||
|
|
||||||
db
|
|
||||||
|
|
||||||
Randomly:
|
|
||||||
|
|
||||||
dr
|
|
||||||
|
|
||||||
|
|
||||||
Shortcuts:
|
|
||||||
|
|
||||||
Redirects:
|
|
||||||
code:msg>destination
|
|
||||||
code>destination
|
|
||||||
|
|
||||||
301:VALUE>VALUE
|
|
||||||
301>http://foo.bar
|
|
||||||
|
|
||||||
|
|
||||||
Content-type:
|
|
||||||
|
|
||||||
t:content-type
|
|
||||||
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
200,b:500k
|
200,b500k
|
||||||
|
404,pb5,b1k:printable
|
||||||
404,p:5s,b:1k:printable
|
200,t"text/json",pr5,b1k
|
||||||
|
200,b1k,xr
|
||||||
200,t:text/json,p:5s,b:1k
|
|
||||||
|
|
||||||
200,b:1k,xr
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Sequences:
|
Sequences:
|
||||||
|
|
||||||
200 * 2 | !forever
|
200 * 2 | !forever
|
||||||
|
|
||||||
200 | 404 | 200,b:500g
|
200 | 404 | 200,b:500g
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Anchors:
|
Anchors:
|
||||||
|
|
||||||
Passed on command-line?
|
Passed on command-line?
|
||||||
|
@ -17,7 +17,7 @@ class DummyRequest(StringIO.StringIO):
|
|||||||
|
|
||||||
class uMisc(libpry.AutoTree):
|
class uMisc(libpry.AutoTree):
|
||||||
def test_generators(self):
|
def test_generators(self):
|
||||||
v = rparse.Value.parseString("val")[0]
|
v = rparse.Value.parseString("'val'")[0]
|
||||||
g = v.get_generator({})
|
g = v.get_generator({})
|
||||||
assert g[:] == "val"
|
assert g[:] == "val"
|
||||||
|
|
||||||
@ -94,26 +94,25 @@ class uMisc(libpry.AutoTree):
|
|||||||
assert v.datatype == "digits"
|
assert v.datatype == "digits"
|
||||||
|
|
||||||
def test_value(self):
|
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"
|
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):
|
def test_body(self):
|
||||||
e = rparse.Body.expr()
|
e = rparse.Body.expr()
|
||||||
v = e.parseString("b:foo")[0]
|
v = e.parseString("b'foo'")[0]
|
||||||
assert v.value.val == "foo"
|
assert v.value.val == "foo"
|
||||||
|
|
||||||
v = e.parseString("b:!100")[0]
|
v = e.parseString("b!100")[0]
|
||||||
assert str(v.value) == "!100b:bytes"
|
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 v.value.datatype == "digits"
|
||||||
assert str(v.value) == "!100g:digits"
|
assert str(v.value) == "!100g:digits"
|
||||||
|
|
||||||
def test_header(self):
|
def test_header(self):
|
||||||
e = rparse.Header.expr()
|
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.key.val == "foo"
|
||||||
assert v.value.val == "bar"
|
assert v.value.val == "bar"
|
||||||
|
|
||||||
@ -122,17 +121,17 @@ class uMisc(libpry.AutoTree):
|
|||||||
v = e.parseString("200")[0]
|
v = e.parseString("200")[0]
|
||||||
assert v.code == 200
|
assert v.code == 200
|
||||||
|
|
||||||
v = e.parseString("404:msg")[0]
|
v = e.parseString("404'msg'")[0]
|
||||||
assert v.code == 404
|
assert v.code == 404
|
||||||
assert v.msg.val == "msg"
|
assert v.msg.val == "msg"
|
||||||
|
|
||||||
r = e.parseString("200:'foo'")[0]
|
r = e.parseString("200'foo'")[0]
|
||||||
assert r.msg.val == "foo"
|
assert r.msg.val == "foo"
|
||||||
|
|
||||||
r = e.parseString("200:'\"foo\"'")[0]
|
r = e.parseString("200'\"foo\"'")[0]
|
||||||
assert r.msg.val == "\"foo\""
|
assert r.msg.val == "\"foo\""
|
||||||
|
|
||||||
r = e.parseString('200:"foo"')[0]
|
r = e.parseString('200"foo"')[0]
|
||||||
assert r.msg.val == "foo"
|
assert r.msg.val == "foo"
|
||||||
|
|
||||||
r = e.parseString('404')[0]
|
r = e.parseString('404')[0]
|
||||||
@ -168,20 +167,20 @@ class uDisconnects(libpry.AutoTree):
|
|||||||
class uPauses(libpry.AutoTree):
|
class uPauses(libpry.AutoTree):
|
||||||
def test_before(self):
|
def test_before(self):
|
||||||
e = rparse.PauseBefore.expr()
|
e = rparse.PauseBefore.expr()
|
||||||
v = e.parseString("pb:10")[0]
|
v = e.parseString("pb10")[0]
|
||||||
assert v.value == 10
|
assert v.value == 10
|
||||||
|
|
||||||
v = e.parseString("pb:forever")[0]
|
v = e.parseString("pbforever")[0]
|
||||||
assert v.value == "forever"
|
assert v.value == "forever"
|
||||||
|
|
||||||
def test_after(self):
|
def test_after(self):
|
||||||
e = rparse.PauseAfter.expr()
|
e = rparse.PauseAfter.expr()
|
||||||
v = e.parseString("pa:10")[0]
|
v = e.parseString("pa10")[0]
|
||||||
assert v.value == 10
|
assert v.value == 10
|
||||||
|
|
||||||
def test_random(self):
|
def test_random(self):
|
||||||
e = rparse.PauseRandom.expr()
|
e = rparse.PauseRandom.expr()
|
||||||
v = e.parseString("pr:10")[0]
|
v = e.parseString("pr10")[0]
|
||||||
assert v.value == 10
|
assert v.value == 10
|
||||||
|
|
||||||
|
|
||||||
@ -191,41 +190,41 @@ class uparse(libpry.AutoTree):
|
|||||||
try:
|
try:
|
||||||
rparse.parse({}, "400:msg,b:")
|
rparse.parse({}, "400:msg,b:")
|
||||||
except rparse.ParseException, v:
|
except rparse.ParseException, v:
|
||||||
print v.marked()
|
assert v.marked()
|
||||||
|
|
||||||
def test_parse_header(self):
|
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"
|
assert r.get_header("foo") == "bar"
|
||||||
|
|
||||||
def test_parse_pause_before(self):
|
def test_parse_pause_before(self):
|
||||||
r = rparse.parse({}, "400,pb:10")
|
r = rparse.parse({}, "400,pb10")
|
||||||
assert (0, 10) in r.pauses
|
assert (0, 10) in r.pauses
|
||||||
|
|
||||||
def test_parse_pause_after(self):
|
def test_parse_pause_after(self):
|
||||||
r = rparse.parse({}, "400,pa:10")
|
r = rparse.parse({}, "400,pa10")
|
||||||
assert (sys.maxint, 10) in r.pauses
|
assert (sys.maxint, 10) in r.pauses
|
||||||
|
|
||||||
def test_parse_pause_random(self):
|
def test_parse_pause_random(self):
|
||||||
r = rparse.parse({}, "400,pr:10")
|
r = rparse.parse({}, "400,pr10")
|
||||||
assert ("random", 10) in r.pauses
|
assert ("random", 10) in r.pauses
|
||||||
|
|
||||||
|
|
||||||
class uResponse(libpry.AutoTree):
|
class uResponse(libpry.AutoTree):
|
||||||
def dummy_response(self):
|
def dummy_response(self):
|
||||||
return rparse.parse({}, "400:msg")
|
return rparse.parse({}, "400'msg'")
|
||||||
|
|
||||||
def test_response(self):
|
def test_response(self):
|
||||||
r = rparse.parse({}, "400:msg")
|
r = rparse.parse({}, "400'msg'")
|
||||||
assert r.code == 400
|
assert r.code == 400
|
||||||
assert r.msg == "msg"
|
assert r.msg == "msg"
|
||||||
|
|
||||||
r = rparse.parse({}, "400:msg,b:!100b")
|
r = rparse.parse({}, "400'msg',b!100b")
|
||||||
assert r.msg == "msg"
|
assert r.msg == "msg"
|
||||||
assert r.body[:]
|
assert r.body[:]
|
||||||
assert str(r)
|
assert str(r)
|
||||||
|
|
||||||
def test_ready_randoms(self):
|
def test_ready_randoms(self):
|
||||||
r = rparse.parse({}, "400:msg")
|
r = rparse.parse({}, "400'msg'")
|
||||||
|
|
||||||
x = [(0, 5)]
|
x = [(0, 5)]
|
||||||
assert r.ready_randoms(100, x) == x
|
assert r.ready_randoms(100, x) == x
|
||||||
@ -246,7 +245,7 @@ class uResponse(libpry.AutoTree):
|
|||||||
|
|
||||||
def test_write_values(self):
|
def test_write_values(self):
|
||||||
tst = "foo"*1025
|
tst = "foo"*1025
|
||||||
r = rparse.parse({}, "400:msg")
|
r = rparse.parse({}, "400'msg'")
|
||||||
|
|
||||||
s = DummyRequest()
|
s = DummyRequest()
|
||||||
r.write_values(s, [tst], [], None)
|
r.write_values(s, [tst], [], None)
|
||||||
@ -254,7 +253,7 @@ class uResponse(libpry.AutoTree):
|
|||||||
|
|
||||||
def test_write_values_pauses(self):
|
def test_write_values_pauses(self):
|
||||||
tst = "".join(str(i) for i in range(10))
|
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):
|
for i in range(2, 10):
|
||||||
s = DummyRequest()
|
s = DummyRequest()
|
||||||
@ -274,7 +273,7 @@ class uResponse(libpry.AutoTree):
|
|||||||
|
|
||||||
def test_render(self):
|
def test_render(self):
|
||||||
s = DummyRequest()
|
s = DummyRequest()
|
||||||
r = rparse.parse({}, "400:msg")
|
r = rparse.parse({}, "400'msg'")
|
||||||
r.render(s)
|
r.render(s)
|
||||||
|
|
||||||
def test_length(self):
|
def test_length(self):
|
||||||
@ -282,9 +281,9 @@ class uResponse(libpry.AutoTree):
|
|||||||
s = DummyRequest()
|
s = DummyRequest()
|
||||||
x.render(s)
|
x.render(s)
|
||||||
assert x.length() == len(s.getvalue())
|
assert x.length() == len(s.getvalue())
|
||||||
testlen(rparse.parse({}, "400:msg"))
|
testlen(rparse.parse({}, "400'msg'"))
|
||||||
testlen(rparse.parse({}, "400:msg,h:foo:bar"))
|
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 = [
|
tests = [
|
||||||
|
Loading…
Reference in New Issue
Block a user