mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
Refactoring: canonical storage of a message is now the sequence of tokens that defines it.
We use a set of accessor properties to ease access to tokens. We can now ditch the .accept() methods.
This commit is contained in:
parent
882969086c
commit
8741600ce7
@ -309,18 +309,8 @@ class _Spec(object):
|
|||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def accept(self, r): # pragma: no cover
|
|
||||||
"""
|
|
||||||
Notifies the component to register itself with message r.
|
|
||||||
"""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class Raw(_Spec):
|
class Raw(_Spec):
|
||||||
def accept(self, r):
|
|
||||||
r.raw = True
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("r").suppress()
|
e = pp.Literal("r").suppress()
|
||||||
@ -357,9 +347,6 @@ class _Header(_Component):
|
|||||||
"\r\n",
|
"\r\n",
|
||||||
]
|
]
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.headers.append(self)
|
|
||||||
|
|
||||||
|
|
||||||
class Header(_Header):
|
class Header(_Header):
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -397,9 +384,6 @@ class Body(_Component):
|
|||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.body = self
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = pp.Literal("b").suppress()
|
e = pp.Literal("b").suppress()
|
||||||
@ -418,9 +402,6 @@ class Path(_Component):
|
|||||||
value = ValueLiteral(value)
|
value = ValueLiteral(value)
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.path = self
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = NakedValue.copy()
|
e = NakedValue.copy()
|
||||||
@ -451,9 +432,6 @@ class Method(_Component):
|
|||||||
value = ValueLiteral(value.upper())
|
value = ValueLiteral(value.upper())
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.method = self
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
parts = [pp.CaselessLiteral(i) for i in klass.methods]
|
parts = [pp.CaselessLiteral(i) for i in klass.methods]
|
||||||
@ -472,9 +450,6 @@ class Code(_Component):
|
|||||||
def __init__(self, code):
|
def __init__(self, code):
|
||||||
self.code = str(code)
|
self.code = str(code)
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.code = self
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
e = v_integer.copy()
|
e = v_integer.copy()
|
||||||
@ -488,8 +463,6 @@ class Reason(_Component):
|
|||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.reason = self
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expr(klass):
|
def expr(klass):
|
||||||
@ -529,9 +502,6 @@ class _Action(_Spec):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.spec()
|
return self.spec()
|
||||||
|
|
||||||
def accept(self, r):
|
|
||||||
r.actions.append(self)
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def spec(self): # pragma: no cover
|
def spec(self): # pragma: no cover
|
||||||
pass
|
pass
|
||||||
@ -610,11 +580,32 @@ class InjectAt(_Action):
|
|||||||
class _Message(object):
|
class _Message(object):
|
||||||
__metaclass__ = abc.ABCMeta
|
__metaclass__ = abc.ABCMeta
|
||||||
version = "HTTP/1.1"
|
version = "HTTP/1.1"
|
||||||
def __init__(self):
|
def __init__(self, tokens):
|
||||||
self.body = None
|
self.tokens = tokens
|
||||||
self.headers = []
|
|
||||||
self.actions = []
|
def _get_tokens(self, klass):
|
||||||
self.raw = False
|
return [i for i in self.tokens if isinstance(i, klass)]
|
||||||
|
|
||||||
|
def _get_token(self, klass):
|
||||||
|
l = self._get_tokens(klass)
|
||||||
|
if l:
|
||||||
|
return l[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def raw(self):
|
||||||
|
return bool(self._get_token(Raw))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def actions(self):
|
||||||
|
return self._get_tokens(_Action)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def body(self):
|
||||||
|
return self._get_token(Body)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def headers(self):
|
||||||
|
return self._get_tokens(_Header)
|
||||||
|
|
||||||
def length(self, settings, request_host):
|
def length(self, settings, request_host):
|
||||||
"""
|
"""
|
||||||
@ -634,7 +625,7 @@ class _Message(object):
|
|||||||
Modify this message to be safe for previews. Returns a list of elided actions.
|
Modify this message to be safe for previews. Returns a list of elided actions.
|
||||||
"""
|
"""
|
||||||
pauses = [i for i in self.actions if isinstance(i, PauseAt)]
|
pauses = [i for i in self.actions if isinstance(i, PauseAt)]
|
||||||
self.actions = [i for i in self.actions if not isinstance(i, PauseAt)]
|
#self.actions = [i for i in self.actions if not isinstance(i, PauseAt)]
|
||||||
return pauses
|
return pauses
|
||||||
|
|
||||||
def maximum_length(self, settings, request_host):
|
def maximum_length(self, settings, request_host):
|
||||||
@ -738,7 +729,7 @@ class _Message(object):
|
|||||||
|
|
||||||
Sep = pp.Optional(pp.Literal(":")).suppress()
|
Sep = pp.Optional(pp.Literal(":")).suppress()
|
||||||
|
|
||||||
class Response(_Message):
|
class _Response(_Message):
|
||||||
comps = (
|
comps = (
|
||||||
Body,
|
Body,
|
||||||
Header,
|
Header,
|
||||||
@ -751,10 +742,13 @@ class Response(_Message):
|
|||||||
Reason
|
Reason
|
||||||
)
|
)
|
||||||
logattrs = ["code", "reason", "version", "body"]
|
logattrs = ["code", "reason", "version", "body"]
|
||||||
def __init__(self):
|
@property
|
||||||
_Message.__init__(self)
|
def code(self):
|
||||||
self.code = None
|
return self._get_token(Code)
|
||||||
self.reason = None
|
|
||||||
|
@property
|
||||||
|
def reason(self):
|
||||||
|
return self._get_token(Reason)
|
||||||
|
|
||||||
def preamble(self, settings):
|
def preamble(self, settings):
|
||||||
l = [self.version, " "]
|
l = [self.version, " "]
|
||||||
@ -779,7 +773,7 @@ class Response(_Message):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
class Request(_Message):
|
class _Request(_Message):
|
||||||
comps = (
|
comps = (
|
||||||
Body,
|
Body,
|
||||||
Header,
|
Header,
|
||||||
@ -790,10 +784,13 @@ class Request(_Message):
|
|||||||
Raw
|
Raw
|
||||||
)
|
)
|
||||||
logattrs = ["method", "path", "body"]
|
logattrs = ["method", "path", "body"]
|
||||||
def __init__(self):
|
@property
|
||||||
_Message.__init__(self)
|
def method(self):
|
||||||
self.method = None
|
return self._get_token(Method)
|
||||||
self.path = None
|
|
||||||
|
@property
|
||||||
|
def path(self):
|
||||||
|
return self._get_token(Path)
|
||||||
|
|
||||||
def preamble(self, settings):
|
def preamble(self, settings):
|
||||||
v = self.method.values(settings)
|
v = self.method.values(settings)
|
||||||
@ -818,44 +815,40 @@ class Request(_Message):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
class CraftedRequest(Request):
|
class CraftedRequest(_Request):
|
||||||
def __init__(self, settings, spec, tokens):
|
def __init__(self, spec, tokens):
|
||||||
Request.__init__(self)
|
_Request.__init__(self, tokens)
|
||||||
self.spec, self.tokens = spec, tokens
|
self.spec, self.tokens = spec, tokens
|
||||||
for i in tokens:
|
|
||||||
i.accept(self)
|
|
||||||
|
|
||||||
def serve(self, fp, settings, host):
|
def serve(self, fp, settings, host):
|
||||||
d = Request.serve(self, fp, settings, host)
|
d = _Request.serve(self, fp, settings, host)
|
||||||
d["spec"] = self.spec
|
d["spec"] = self.spec
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class CraftedResponse(Response):
|
class CraftedResponse(_Response):
|
||||||
def __init__(self, settings, spec, tokens):
|
def __init__(self, spec, tokens):
|
||||||
Response.__init__(self)
|
_Response.__init__(self, tokens)
|
||||||
self.spec, self.tokens = spec, tokens
|
self.spec, self.tokens = spec, tokens
|
||||||
for i in tokens:
|
|
||||||
i.accept(self)
|
|
||||||
|
|
||||||
def serve(self, fp, settings):
|
def serve(self, fp, settings):
|
||||||
d = Response.serve(self, fp, settings, None)
|
d = _Response.serve(self, fp, settings, None)
|
||||||
d["spec"] = self.spec
|
d["spec"] = self.spec
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class PathodErrorResponse(Response):
|
class PathodErrorResponse(_Response):
|
||||||
def __init__(self, msg, body=None):
|
def __init__(self, reason, body=None):
|
||||||
Response.__init__(self)
|
tokens = [
|
||||||
self.code = Code("800")
|
Code("800"),
|
||||||
self.msg = LiteralGenerator(msg)
|
|
||||||
self.body = Body(ValueLiteral("pathod error: " + (body or msg)))
|
|
||||||
self.headers = [
|
|
||||||
Header(ValueLiteral("Content-Type"), ValueLiteral("text/plain")),
|
Header(ValueLiteral("Content-Type"), ValueLiteral("text/plain")),
|
||||||
|
Reason(ValueLiteral(reason)),
|
||||||
|
Body(ValueLiteral("pathod error: " + (body or reason))),
|
||||||
]
|
]
|
||||||
|
_Response.__init__(self, tokens)
|
||||||
|
|
||||||
def serve(self, fp, settings):
|
def serve(self, fp, settings):
|
||||||
d = Response.serve(self, fp, settings, None)
|
d = _Response.serve(self, fp, settings, None)
|
||||||
d["internal"] = True
|
d["internal"] = True
|
||||||
return d
|
return d
|
||||||
|
|
||||||
@ -888,7 +881,7 @@ def parse_response(settings, s):
|
|||||||
if s.startswith(FILESTART):
|
if s.startswith(FILESTART):
|
||||||
s = read_file(settings, s)
|
s = read_file(settings, s)
|
||||||
try:
|
try:
|
||||||
return CraftedResponse(settings, s, Response.expr().parseString(s, parseAll=True))
|
return CraftedResponse(s, _Response.expr().parseString(s, parseAll=True))
|
||||||
except pp.ParseException, v:
|
except pp.ParseException, v:
|
||||||
raise ParseException(v.msg, v.line, v.col)
|
raise ParseException(v.msg, v.line, v.col)
|
||||||
|
|
||||||
@ -904,6 +897,6 @@ def parse_request(settings, s):
|
|||||||
if s.startswith(FILESTART):
|
if s.startswith(FILESTART):
|
||||||
s = read_file(settings, s)
|
s = read_file(settings, s)
|
||||||
try:
|
try:
|
||||||
return CraftedRequest(settings, s, Request.expr().parseString(s, parseAll=True))
|
return CraftedRequest(s, _Request.expr().parseString(s, parseAll=True))
|
||||||
except pp.ParseException, v:
|
except pp.ParseException, v:
|
||||||
raise ParseException(v.msg, v.line, v.col)
|
raise ParseException(v.msg, v.line, v.col)
|
||||||
|
@ -542,32 +542,20 @@ class TestResponse:
|
|||||||
testlen(language.parse_response({}, "400:m'msg':h'foo'='bar':b@100b"))
|
testlen(language.parse_response({}, "400:m'msg':h'foo'='bar':b@100b"))
|
||||||
|
|
||||||
def test_maximum_length(self):
|
def test_maximum_length(self):
|
||||||
def testlen(x, actions):
|
def testlen(x):
|
||||||
s = cStringIO.StringIO()
|
s = cStringIO.StringIO()
|
||||||
m = x.maximum_length({}, None)
|
m = x.maximum_length({}, None)
|
||||||
x.serve(s, {})
|
x.serve(s, {})
|
||||||
assert m >= len(s.getvalue())
|
assert m >= len(s.getvalue())
|
||||||
|
|
||||||
r = language.parse_response({}, "400:m'msg':b@100")
|
r = language.parse_response({}, "400:m'msg':b@100:d0")
|
||||||
|
testlen(r)
|
||||||
|
|
||||||
actions = [
|
r = language.parse_response({}, "400:m'msg':b@100:d0:i0,'foo'")
|
||||||
language.DisconnectAt(0)
|
testlen(r)
|
||||||
]
|
|
||||||
r.actions = actions
|
|
||||||
testlen(r, actions)
|
|
||||||
|
|
||||||
actions = [
|
r = language.parse_response({}, "400:m'msg':b@100:d0:i0,'foo'")
|
||||||
language.DisconnectAt(0),
|
testlen(r)
|
||||||
language.InjectAt(0, language.ValueLiteral("foo"))
|
|
||||||
]
|
|
||||||
r.actions = actions
|
|
||||||
testlen(r, actions)
|
|
||||||
|
|
||||||
actions = [
|
|
||||||
language.InjectAt(0, language.ValueLiteral("foo"))
|
|
||||||
]
|
|
||||||
r.actions = actions
|
|
||||||
testlen(r, actions)
|
|
||||||
|
|
||||||
def test_render(self):
|
def test_render(self):
|
||||||
r = language.parse_response({}, "400:p0,100:dr")
|
r = language.parse_response({}, "400:p0,100:dr")
|
||||||
|
Loading…
Reference in New Issue
Block a user