mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 10:16:27 +00:00
Basic client playback state structure.
This commit is contained in:
parent
2e492b8e94
commit
96471fde1d
@ -26,34 +26,58 @@ class RequestReplayThread(threading.Thread):
|
|||||||
response = server.read_response()
|
response = server.read_response()
|
||||||
response.send(self.masterq)
|
response.send(self.masterq)
|
||||||
except proxy.ProxyError, v:
|
except proxy.ProxyError, v:
|
||||||
err = proxy.Error(self.flow.client_conn, v.msg)
|
err = proxy.Error(self.flow.request, v.msg)
|
||||||
err.send(self.masterq)
|
err.send(self.masterq)
|
||||||
# end nocover
|
# end nocover
|
||||||
|
|
||||||
|
|
||||||
|
class ClientPlaybackState:
|
||||||
|
def __init__(self, flows):
|
||||||
|
self.flows = flows
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
def count(self):
|
||||||
|
return len(self.flows)
|
||||||
|
|
||||||
|
def clear(self, flow):
|
||||||
|
"""
|
||||||
|
A request has returned in some way - if this is the one we're
|
||||||
|
servicing, go to the next flow.
|
||||||
|
"""
|
||||||
|
if flow is self.current:
|
||||||
|
self.current = None
|
||||||
|
|
||||||
|
def tick(self, master, testing=False):
|
||||||
|
"""
|
||||||
|
testing: Disables actual replay for testing.
|
||||||
|
"""
|
||||||
|
if self.flows and not self.current:
|
||||||
|
self.current = self.flows.pop(0)
|
||||||
|
self.current.response = None
|
||||||
|
master.handle_request(self.current.request)
|
||||||
|
if not testing:
|
||||||
|
#begin nocover
|
||||||
|
master.state.replay_request(self.current, master.masterq)
|
||||||
|
#end nocover
|
||||||
|
|
||||||
|
|
||||||
class ServerPlaybackState:
|
class ServerPlaybackState:
|
||||||
def __init__(self, headers):
|
def __init__(self, headers, flows):
|
||||||
"""
|
"""
|
||||||
headers: A case-insensitive list of request headers that should be
|
headers: A case-insensitive list of request headers that should be
|
||||||
included in request-response matching.
|
included in request-response matching.
|
||||||
"""
|
"""
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.fmap = {}
|
self.fmap = {}
|
||||||
|
|
||||||
def count(self):
|
|
||||||
return sum([len(i) for i in self.fmap.values()])
|
|
||||||
|
|
||||||
def load(self, flows):
|
|
||||||
"""
|
|
||||||
Load a sequence of flows. We assume that the sequence is in
|
|
||||||
chronological order.
|
|
||||||
"""
|
|
||||||
for i in flows:
|
for i in flows:
|
||||||
if i.response:
|
if i.response:
|
||||||
h = self._hash(i)
|
h = self._hash(i)
|
||||||
l = self.fmap.setdefault(self._hash(i), [])
|
l = self.fmap.setdefault(self._hash(i), [])
|
||||||
l.append(i)
|
l.append(i)
|
||||||
|
|
||||||
|
def count(self):
|
||||||
|
return sum([len(i) for i in self.fmap.values()])
|
||||||
|
|
||||||
def _hash(self, flow):
|
def _hash(self, flow):
|
||||||
"""
|
"""
|
||||||
Calculates a loose hash of the flow request.
|
Calculates a loose hash of the flow request.
|
||||||
@ -415,8 +439,7 @@ class FlowMaster(controller.Master):
|
|||||||
flows: A list of flows.
|
flows: A list of flows.
|
||||||
kill: Boolean, should we kill requests not part of the replay?
|
kill: Boolean, should we kill requests not part of the replay?
|
||||||
"""
|
"""
|
||||||
self.playback = ServerPlaybackState(headers)
|
self.playback = ServerPlaybackState(headers, flows)
|
||||||
self.playback.load(flows)
|
|
||||||
self.kill_nonreplay = kill
|
self.kill_nonreplay = kill
|
||||||
|
|
||||||
def do_playback(self, flow):
|
def do_playback(self, flow):
|
||||||
|
@ -33,10 +33,32 @@ class uStickyCookieState(libpry.AutoTree):
|
|||||||
assert "cookie" in f.request.headers
|
assert "cookie" in f.request.headers
|
||||||
|
|
||||||
|
|
||||||
|
class uClientPlaybackState(libpry.AutoTree):
|
||||||
|
def test_tick(self):
|
||||||
|
first = utils.tflow()
|
||||||
|
c = flow.ClientPlaybackState(
|
||||||
|
[first, utils.tflow()]
|
||||||
|
)
|
||||||
|
s = flow.State()
|
||||||
|
fm = flow.FlowMaster(None, s)
|
||||||
|
assert not s.flow_map
|
||||||
|
assert c.count() == 2
|
||||||
|
c.tick(fm, testing=True)
|
||||||
|
assert s.flow_map
|
||||||
|
assert c.count() == 1
|
||||||
|
|
||||||
|
c.tick(fm, testing=True)
|
||||||
|
assert c.count() == 1
|
||||||
|
|
||||||
|
c.clear(first)
|
||||||
|
c.tick(fm, testing=True)
|
||||||
|
assert c.count() == 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class uServerPlaybackState(libpry.AutoTree):
|
class uServerPlaybackState(libpry.AutoTree):
|
||||||
def test_hash(self):
|
def test_hash(self):
|
||||||
s = flow.ServerPlaybackState(None)
|
s = flow.ServerPlaybackState(None, [])
|
||||||
r = utils.tflow()
|
r = utils.tflow()
|
||||||
r2 = utils.tflow()
|
r2 = utils.tflow()
|
||||||
|
|
||||||
@ -48,7 +70,7 @@ class uServerPlaybackState(libpry.AutoTree):
|
|||||||
assert s._hash(r) != s._hash(r2)
|
assert s._hash(r) != s._hash(r2)
|
||||||
|
|
||||||
def test_headers(self):
|
def test_headers(self):
|
||||||
s = flow.ServerPlaybackState(["foo"])
|
s = flow.ServerPlaybackState(["foo"], [])
|
||||||
r = utils.tflow_full()
|
r = utils.tflow_full()
|
||||||
r.request.headers["foo"] = ["bar"]
|
r.request.headers["foo"] = ["bar"]
|
||||||
r2 = utils.tflow_full()
|
r2 = utils.tflow_full()
|
||||||
@ -63,14 +85,13 @@ class uServerPlaybackState(libpry.AutoTree):
|
|||||||
assert s._hash(r) == s._hash(r2)
|
assert s._hash(r) == s._hash(r2)
|
||||||
|
|
||||||
def test_load(self):
|
def test_load(self):
|
||||||
s = flow.ServerPlaybackState(None)
|
|
||||||
r = utils.tflow_full()
|
r = utils.tflow_full()
|
||||||
r.request.headers["key"] = ["one"]
|
r.request.headers["key"] = ["one"]
|
||||||
|
|
||||||
r2 = utils.tflow_full()
|
r2 = utils.tflow_full()
|
||||||
r2.request.headers["key"] = ["two"]
|
r2.request.headers["key"] = ["two"]
|
||||||
|
|
||||||
s.load([r, r2])
|
s = flow.ServerPlaybackState(None, [r, r2])
|
||||||
assert s.count() == 2
|
assert s.count() == 2
|
||||||
assert len(s.fmap.keys()) == 1
|
assert len(s.fmap.keys()) == 1
|
||||||
|
|
||||||
@ -398,6 +419,7 @@ class uFlowMaster(libpry.AutoTree):
|
|||||||
tests = [
|
tests = [
|
||||||
uStickyCookieState(),
|
uStickyCookieState(),
|
||||||
uServerPlaybackState(),
|
uServerPlaybackState(),
|
||||||
|
uClientPlaybackState(),
|
||||||
uFlow(),
|
uFlow(),
|
||||||
uState(),
|
uState(),
|
||||||
uSerialize(),
|
uSerialize(),
|
||||||
|
Loading…
Reference in New Issue
Block a user