def test_cut(): c = cut.Cut() with taddons.context(): tflows = [tflow.tflow(resp=True)] assert c.cut(tflows, ["request.method"]) == [["GET"]] assert c.cut(tflows, ["request.scheme"]) == [["http"]] assert c.cut(tflows, ["request.host"]) == [["address"]] assert c.cut(tflows, ["request.port"]) == [["22"]] assert c.cut(tflows, ["request.path"]) == [["/path"]] assert c.cut(tflows, ["request.url"]) == [["http://address:22/path"]] assert c.cut(tflows, ["request.content"]) == [[b"content"]] assert c.cut(tflows, ["request.header[header]"]) == [["qvalue"]] assert c.cut(tflows, ["request.header[unknown]"]) == [[""]] assert c.cut(tflows, ["response.status_code"]) == [["200"]] assert c.cut(tflows, ["response.reason"]) == [["OK"]] assert c.cut(tflows, ["response.content"]) == [[b"message"]] assert c.cut(tflows, ["response.header[header-response]"]) == [["svalue"]] assert c.cut(tflows, ["moo"]) == [[""]] with pytest.raises(exceptions.CommandError): assert c.cut(tflows, ["__dict__"]) == [[""]] with taddons.context(): tflows = [tflow.tflow(resp=False)] assert c.cut(tflows, ["response.reason"]) == [[""]] assert c.cut(tflows, ["response.header[key]"]) == [[""]] c = cut.Cut() with taddons.context(): tflows = [tflow.ttcpflow()] assert c.cut(tflows, ["request.method"]) == [[""]] assert c.cut(tflows, ["response.status"]) == [[""]]
def test_cut(): v = view.View() c = cut.Cut() with taddons.context() as tctx: v.add([tflow.tflow(resp=True)]) tctx.master.addons.add(v, c) assert c.cut("q.method|@all") == [["GET"]] assert c.cut("q.scheme|@all") == [["http"]] assert c.cut("q.host|@all") == [["address"]] assert c.cut("q.port|@all") == [["22"]] assert c.cut("q.path|@all") == [["/path"]] assert c.cut("q.url|@all") == [["http://*****:*****@all") == [[b"content"]] assert c.cut("q.header[header]|@all") == [["qvalue"]] assert c.cut("q.header[unknown]|@all") == [[""]] assert c.cut("s.status_code|@all") == [["200"]] assert c.cut("s.reason|@all") == [["OK"]] assert c.cut("s.content|@all") == [[b"message"]] assert c.cut("s.header[header-response]|@all") == [["svalue"]] assert c.cut("moo") == [[""]] with pytest.raises(exceptions.CommandError): assert c.cut("__dict__") == [[""]] v = view.View() c = cut.Cut() with taddons.context() as tctx: tctx.master.addons.add(v, c) v.add([tflow.ttcpflow()]) assert c.cut("q.method|@all") == [[""]] assert c.cut("s.status|@all") == [[""]]
def test_decorator(): with taddons.context() as tctx: c = command.CommandManager(tctx.master) a = TDec() c.collect_commands(a) assert "cmd1" in c.commands assert c.execute("cmd1 bar") == "ret bar" assert "empty" in c.commands assert c.execute("empty") is None with taddons.context() as tctx: tctx.master.addons.add(a) assert tctx.master.commands.execute("cmd1 bar") == "ret bar"
def test_focus_follow(): v = view.View() with taddons.context() as tctx: console_addon = consoleaddons.ConsoleAddon(tctx.master) tctx.configure(console_addon) tctx.configure(v, console_focus_follow=True, view_filter="~m get") v.add([tft(start=5)]) assert v.focus.index == 0 v.add([tft(start=4)]) assert v.focus.index == 0 assert v.focus.flow.request.timestamp_start == 4 v.add([tft(start=7)]) assert v.focus.index == 2 assert v.focus.flow.request.timestamp_start == 7 mod = tft(method="put", start=6) v.add([mod]) assert v.focus.index == 2 assert v.focus.flow.request.timestamp_start == 7 mod.request.method = "GET" v.update([mod]) assert v.focus.index == 2 assert v.focus.flow.request.timestamp_start == 6
def test_movement(): v = view.View() with taddons.context(): v.go(0) v.add([ tflow.tflow(), tflow.tflow(), tflow.tflow(), tflow.tflow(), tflow.tflow(), ]) assert v.focus.index == 0 v.go(-1) assert v.focus.index == 4 v.go(0) assert v.focus.index == 0 v.go(1) assert v.focus.index == 1 v.go(999) assert v.focus.index == 4 v.go(-999) assert v.focus.index == 0 v.focus_next() assert v.focus.index == 1 v.focus_prev() assert v.focus.index == 0
def test_ignore_content(): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: tctx.configure(s, server_replay_ignore_content=False) r = tflow.tflow(resp=True) r2 = tflow.tflow(resp=True) r.request.content = b"foo" r2.request.content = b"foo" assert s._hash(r) == s._hash(r2) r2.request.content = b"bar" assert not s._hash(r) == s._hash(r2) tctx.configure(s, server_replay_ignore_content=True) r = tflow.tflow(resp=True) r2 = tflow.tflow(resp=True) r.request.content = b"foo" r2.request.content = b"foo" assert s._hash(r) == s._hash(r2) r2.request.content = b"bar" assert s._hash(r) == s._hash(r2) r2.request.content = b"" assert s._hash(r) == s._hash(r2) r2.request.content = None assert s._hash(r) == s._hash(r2)
def test_flow_set(): sa = core.Core() with taddons.context(loadcore=False): f = tflow.tflow(resp=True) assert sa.flow_set_options() assert f.request.method != "post" sa.flow_set([f], "method", "post") assert f.request.method == "POST" assert f.request.host != "testhost" sa.flow_set([f], "host", "testhost") assert f.request.host == "testhost" assert f.request.path != "/test/path" sa.flow_set([f], "path", "/test/path") assert f.request.path == "/test/path" assert f.request.url != "http://foo.com/bar" sa.flow_set([f], "url", "http://foo.com/bar") assert f.request.url == "http://foo.com/bar" with pytest.raises(exceptions.CommandError): sa.flow_set([f], "url", "oink") assert f.response.status_code != 404 sa.flow_set([f], "status_code", "404") assert f.response.status_code == 404 assert f.response.reason == "Not Found" with pytest.raises(exceptions.CommandError): sa.flow_set([f], "status_code", "oink") assert f.response.reason != "foo" sa.flow_set([f], "reason", "foo") assert f.response.reason == "foo"
def test_authenticate(self): up = proxyauth.ProxyAuth() with taddons.context(up, loadcore=False) as ctx: ctx.configure(up, proxyauth="any", mode="regular") f = tflow.tflow() assert not f.response up.authenticate(f) assert f.response.status_code == 407 f = tflow.tflow() f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( "test", "test" ) up.authenticate(f) assert not f.response assert not f.request.headers.get("Proxy-Authorization") f = tflow.tflow() ctx.configure(up, mode="reverse") assert not f.response up.authenticate(f) assert f.response.status_code == 401 f = tflow.tflow() f.request.headers["Authorization"] = proxyauth.mkauth( "test", "test" ) up.authenticate(f) assert not f.response assert not f.request.headers.get("Authorization")
def test_load(): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: tctx.configure(s) r = tflow.tflow(resp=True) r.request.headers["key"] = "one" r2 = tflow.tflow(resp=True) r2.request.headers["key"] = "two" s.load_flows([r, r2]) assert s.count() == 2 n = s.next_flow(r) assert n.request.headers["key"] == "one" assert s.count() == 1 n = s.next_flow(r) assert n.request.headers["key"] == "two" assert not s.flowmap assert s.count() == 0 assert not s.next_flow(r)
def test_simple(self): r = replace.ReplaceFile() with tutils.tmpdir() as td: rp = os.path.join(td, "replacement") with open(rp, "w") as f: f.write("bar") with taddons.context() as tctx: tctx.configure( r, replacement_files = [ ("~q", "foo", rp), ("~s", "foo", rp), ("~b nonexistent", "nonexistent", "nonexistent"), ] ) f = tflow.tflow() f.request.content = b"foo" r.request(f) assert f.request.content == b"bar" f = tflow.tflow(resp=True) f.response.content = b"foo" r.response(f) assert f.response.content == b"bar" f = tflow.tflow() f.request.content = b"nonexistent" assert not tctx.master.event_log r.request(f) assert tctx.master.event_log
def thash(r, r2, setter): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: s = serverplayback.ServerPlayback() tctx.configure( s, server_replay_ignore_payload_params=["param1", "param2"] ) setter(r, paramx="x", param1="1") setter(r2, paramx="x", param1="1") # same parameters assert s._hash(r) == s._hash(r2) # ignored parameters != setter(r2, paramx="x", param1="2") assert s._hash(r) == s._hash(r2) # missing parameter setter(r2, paramx="x") assert s._hash(r) == s._hash(r2) # ignorable parameter added setter(r2, paramx="x", param1="2") assert s._hash(r) == s._hash(r2) # not ignorable parameter changed setter(r2, paramx="y", param1="1") assert not s._hash(r) == s._hash(r2) # not ignorable parameter missing setter(r2, param1="1") r2.request.content = b"param1=1" assert not s._hash(r) == s._hash(r2)
def test_encoding(): sa = core.Core() with taddons.context(): f = tflow.tflow() assert sa.encode_options() sa.encode([f], "request", "deflate") assert f.request.headers["content-encoding"] == "deflate" sa.encode([f], "request", "br") assert f.request.headers["content-encoding"] == "deflate" sa.decode([f], "request") assert "content-encoding" not in f.request.headers sa.encode([f], "request", "br") assert f.request.headers["content-encoding"] == "br" sa.encode_toggle([f], "request") assert "content-encoding" not in f.request.headers sa.encode_toggle([f], "request") assert f.request.headers["content-encoding"] == "deflate" sa.encode_toggle([f], "request") assert "content-encoding" not in f.request.headers with pytest.raises(exceptions.CommandError): sa.encode([f], "request", "invalid")
def test_options(tmpdir): p = str(tmpdir.join("path")) sa = core.Core() with taddons.context() as tctx: tctx.options.stickycookie = "foo" assert tctx.options.stickycookie == "foo" sa.options_reset() assert tctx.options.stickycookie is None tctx.options.stickycookie = "foo" tctx.options.stickyauth = "bar" sa.options_reset_one("stickycookie") assert tctx.options.stickycookie is None assert tctx.options.stickyauth == "bar" with pytest.raises(exceptions.CommandError): sa.options_reset_one("unknown") sa.options_save(p) with pytest.raises(exceptions.CommandError): sa.options_save("/") sa.options_reset() assert tctx.options.stickyauth is None sa.options_load(p) assert tctx.options.stickyauth == "bar" sa.options_load("/nonexistent") with open(p, 'a') as f: f.write("'''") with pytest.raises(exceptions.CommandError): sa.options_load(p)
def test_normal(self, load_flow, tmpdir, data): rf = readfile.ReadFileStdin() with taddons.context(): tfile = tmpdir.join("tfile") tfile.write(data.getvalue()) rf.load_flows_from_path(str(tfile)) assert load_flow.called
def test_playback(self): cp = clientplayback.ClientPlayback() with taddons.context(): assert cp.count() == 0 f = tflow.tflow(resp=True) cp.load([f]) assert cp.count() == 1 RP = "mitmproxy.proxy.protocol.http_replay.RequestReplayThread" with mock.patch(RP) as rp: assert not cp.current_thread cp.tick() assert rp.called assert cp.current_thread cp.keepserving = False cp.flows = None cp.current_thread = None with mock.patch("mitmproxy.master.Master.shutdown") as sd: cp.tick() assert sd.called cp.current_thread = MockThread() with mock.patch("mitmproxy.master.Master.shutdown") as sd: cp.tick() assert cp.current_thread is None
def test_unknown(): with taddons.context() as tctx: b = mitmproxy.types._UnknownType() assert b.is_valid(tctx.master.commands, mitmproxy.types.Unknown, "foo") is False assert b.is_valid(tctx.master.commands, mitmproxy.types.Unknown, 1) is False assert b.completion(tctx.master.commands, mitmproxy.types.Unknown, "") == [] assert b.parse(tctx.master.commands, mitmproxy.types.Unknown, "foo") == "foo"
def test_path(): with taddons.context() as tctx: b = mitmproxy.types._PathType() assert b.parse(tctx.master.commands, mitmproxy.types.Path, "/foo") == "/foo" assert b.parse(tctx.master.commands, mitmproxy.types.Path, "/bar") == "/bar" assert b.is_valid(tctx.master.commands, mitmproxy.types.Path, "foo") is True assert b.is_valid(tctx.master.commands, mitmproxy.types.Path, 3) is False def normPathOpts(prefix, match): ret = [] for s in b.completion(tctx.master.commands, mitmproxy.types.Path, match): s = s[len(prefix):] s = s.replace(os.sep, "/") ret.append(s) return ret cd = os.path.normpath(tutils.test_data.path("mitmproxy/completion")) assert normPathOpts(cd, cd) == ['/aaa', '/aab', '/aac', '/bbb/'] assert normPathOpts(cd, os.path.join(cd, "a")) == ['/aaa', '/aab', '/aac'] with chdir(cd): assert normPathOpts("", "./") == ['./aaa', './aab', './aac', './bbb/'] assert normPathOpts("", "") == ['./aaa', './aab', './aac', './bbb/'] assert b.completion( tctx.master.commands, mitmproxy.types.Path, "nonexistent" ) == ["nonexistent"]
def test_arg(): with taddons.context() as tctx: b = mitmproxy.types._ArgType() assert b.completion(tctx.master.commands, mitmproxy.types.Arg, "") == [] assert b.parse(tctx.master.commands, mitmproxy.types.Arg, "foo") == "foo" assert b.is_valid(tctx.master.commands, mitmproxy.types.Arg, "foo") is True assert b.is_valid(tctx.master.commands, mitmproxy.types.Arg, 1) is False
def test_str(): with taddons.context() as tctx: b = mitmproxy.types._StrType() assert b.is_valid(tctx.master.commands, str, "foo") is True assert b.is_valid(tctx.master.commands, str, 1) is False assert b.completion(tctx.master.commands, str, "") == [] assert b.parse(tctx.master.commands, str, "foo") == "foo"
def test_simple(): sa = streambodies.StreamBodies() with taddons.context() as tctx: with pytest.raises(exceptions.OptionsError): tctx.configure(sa, stream_large_bodies = "invalid") tctx.configure(sa, stream_large_bodies = "10") f = tflow.tflow() f.request.content = b"" f.request.headers["Content-Length"] = "1024" assert not f.request.stream sa.requestheaders(f) assert f.request.stream f = tflow.tflow(resp=True) f.response.content = b"" f.response.headers["Content-Length"] = "1024" assert not f.response.stream sa.responseheaders(f) assert f.response.stream f = tflow.tflow(resp=True) f.response.headers["content-length"] = "invalid" tctx.cycle(sa, f) tctx.configure(sa, stream_websockets = True) f = tflow.twebsocketflow() assert not f.stream sa.websocket_start(f) assert f.stream
def test_echo_request_line(): sio = io.StringIO() d = dumper.Dumper(sio) with taddons.context(options=options.Options()) as ctx: ctx.configure(d, flow_detail=3, showhost=True) f = tflow.tflow(client_conn=None, server_conn=True, resp=True) f.request.is_replay = True d._echo_request_line(f) assert "[replay]" in sio.getvalue() sio.truncate(0) f = tflow.tflow(client_conn=None, server_conn=True, resp=True) f.request.is_replay = False d._echo_request_line(f) assert "[replay]" not in sio.getvalue() sio.truncate(0) f = tflow.tflow(client_conn=None, server_conn=True, resp=True) f.request.http_version = "nonstandard" d._echo_request_line(f) assert "nonstandard" in sio.getvalue() sio.truncate(0) ctx.configure(d, flow_detail=0, showhost=True) f = tflow.tflow(client_conn=None, server_conn=True, resp=True) terminalWidth = max(shutil.get_terminal_size()[0] - 25, 50) f.request.url = "http://address:22/" + ("x" * terminalWidth) + "textToBeTruncated" d._echo_request_line(f) assert "textToBeTruncated" not in sio.getvalue() sio.truncate(0)
def test_handlers(self): up = proxyauth.ProxyAuth() with taddons.context(up) as ctx: ctx.configure(up, proxyauth="any", mode="regular") f = tflow.tflow() assert not f.response up.requestheaders(f) assert f.response.status_code == 407 f = tflow.tflow() f.request.method = "CONNECT" assert not f.response up.http_connect(f) assert f.response.status_code == 407 f = tflow.tflow() f.request.method = "CONNECT" f.request.headers["Proxy-Authorization"] = proxyauth.mkauth( "test", "test" ) up.http_connect(f) assert not f.response f2 = tflow.tflow(client_conn=f.client_conn) up.requestheaders(f2) assert not f2.response assert f2.metadata["proxyauth"] == ('test', 'test')
def test_check_alpn(self): msg = 'ALPN support missing' with taddons.context() as tctx: a = check_alpn.CheckALPN() tctx.configure(a) assert not tctx.master.has_log(msg)
def test_bind(): with taddons.context() as tctx: km = keymap.Keymap(tctx.master) km.executor = mock.Mock() with pytest.raises(ValueError): km.add("foo", "bar", ["unsupported"]) km.add("key", "str", ["options", "commands"]) assert km.get("options", "key") assert km.get("commands", "key") assert not km.get("flowlist", "key") assert len((km.list("commands"))) == 1 km.handle("unknown", "unknown") assert not km.executor.called km.handle("options", "key") assert km.executor.called km.add("glob", "str", ["global"]) km.executor = mock.Mock() km.handle("options", "glob") assert km.executor.called assert len((km.list("global"))) == 1
def test_simple(): with taddons.context() as tctx: a = tctx.master.addons assert len(a) == 0 a.add(TAddon("one")) assert a.get("one") assert not a.get("two") assert len(a) == 1 a.clear() assert len(a) == 0 assert not a.chain a.add(TAddon("one")) a.trigger("done") a.trigger("tick") assert tctx.master.has_log("not callable") tctx.master.clear() a.get("one").tick = addons a.trigger("tick") assert not tctx.master.has_log("not callable") a.remove(a.get("one")) assert not a.get("one") ta = TAddon("one") a.add(ta) a.trigger("custom") assert ta.custom_called assert ta in a
def test_playback(self): cp = clientplayback.ClientPlayback() with taddons.context() as tctx: assert cp.count() == 0 f = tflow.tflow(resp=True) cp.start_replay([f]) assert cp.count() == 1 RP = "mitmproxy.proxy.protocol.http_replay.RequestReplayThread" with mock.patch(RP) as rp: assert not cp.current_thread cp.tick() assert rp.called assert cp.current_thread cp.flows = [] cp.current_thread.is_alive.return_value = False assert cp.count() == 1 cp.tick() assert cp.count() == 0 assert tctx.master.has_event("update") assert tctx.master.has_event("processing_complete") cp.current_thread = MockThread() cp.tick() assert cp.current_thread is None cp.start_replay([f]) cp.stop_replay() assert not cp.flows
def test_options(tmpdir): p = str(tmpdir.join("path")) sa = core.Core() with taddons.context() as tctx: tctx.options.listen_host = "foo" assert tctx.options.listen_host == "foo" sa.options_reset_one("listen_host") assert tctx.options.listen_host != "foo" with pytest.raises(exceptions.CommandError): sa.options_reset_one("unknown") tctx.options.listen_host = "foo" sa.options_save(p) with pytest.raises(exceptions.CommandError): sa.options_save("/") sa.options_reset() assert tctx.options.listen_host == "" sa.options_load(p) assert tctx.options.listen_host == "foo" sa.options_load("/nonexistent") with open(p, 'a') as f: f.write("'''") with pytest.raises(exceptions.CommandError): sa.options_load(p)
def test_simple(): with taddons.context() as tctx: c = command.CommandManager(tctx.master) a = TAddon() c.add("one.two", a.cmd1) assert c.commands["one.two"].help == "cmd1 help" assert(c.execute("one.two foo") == "ret foo") assert(c.call("one.two", "foo") == "ret foo") with pytest.raises(exceptions.CommandError, match="Unknown"): c.execute("nonexistent") with pytest.raises(exceptions.CommandError, match="Invalid"): c.execute("") with pytest.raises(exceptions.CommandError, match="argument mismatch"): c.execute("one.two too many args") with pytest.raises(exceptions.CommandError, match="Unknown"): c.call("nonexistent") with pytest.raises(exceptions.CommandError, match="No escaped"): c.execute("\\") c.add("empty", a.empty) c.execute("empty") fp = io.StringIO() c.dump(fp) assert fp.getvalue()
def fill_history(self, commands): with taddons.context() as tctx: history = commander.CommandHistory(tctx.master, size=3) for c in commands: cbuf = commander.CommandBuffer(tctx.master, c) history.add_command(cbuf) return history, tctx.master
def test_simple(): r = intercept.Intercept() with taddons.context(options=Options()) as tctx: assert not r.filt tctx.configure(r, intercept="~q") assert r.filt with pytest.raises(exceptions.OptionsError): tctx.configure(r, intercept="~~") tctx.configure(r, intercept=None) assert not r.filt tctx.configure(r, intercept="~s") f = tflow.tflow(resp=True) tctx.cycle(r, f) assert f.intercepted f = tflow.tflow(resp=False) tctx.cycle(r, f) assert not f.intercepted f = tflow.tflow(resp=True) f.reply._state = "handled" r.response(f) assert f.intercepted
def test_simple(self): with taddons.context() as tctx: sc = script.Script( tutils.test_data.path( "mitmproxy/data/addonscripts/recorder/recorder.py")) tctx.master.addons.add(sc) tctx.configure(sc) sc.tick() rec = tctx.master.addons.get("recorder") assert rec.call_log[0][0:2] == ("recorder", "load") rec.call_log = [] f = tflow.tflow(resp=True) tctx.master.addons.trigger("request", f) assert rec.call_log[0][1] == "request"
def test_configure(self): mr = mapremote.MapRemote() with taddons.context(mr) as tctx: tctx.configure(mr, map_remote=["one/two/three"]) with pytest.raises( Exception, match="Cannot parse map_remote .* Invalid number"): tctx.configure(mr, map_remote=["/"]) with pytest.raises( Exception, match="Cannot parse map_remote .* Invalid filter"): tctx.configure(mr, map_remote=["/~b/two/three"]) with pytest.raises( Exception, match= "Cannot parse map_remote .* Invalid regular expression"): tctx.configure(mr, map_remote=["/foo/+/three"]) tctx.configure(mr, map_remote=["/a/b/c/"])
async def test_script_deletion(self, tdata): tdir = tdata.path("mitmproxy/data/addonscripts/") with open(tdir + "/dummy.py", 'w') as f: f.write("\n") with taddons.context() as tctx: sl = script.ScriptLoader() tctx.master.addons.add(sl) tctx.configure( sl, scripts=[tdata.path("mitmproxy/data/addonscripts/dummy.py")]) await tctx.master.await_log("Loading") os.remove(tdata.path("mitmproxy/data/addonscripts/dummy.py")) await tctx.master.await_log("Removing") assert not tctx.options.scripts assert not sl.addons
def test_response_weird(self): sc = stickycookie.StickyCookie() with taddons.context(sc) as tctx: tctx.configure(sc, stickycookie=".*") # Test setting of weird cookie keys f = tflow.tflow(req=ntutils.treq(host="www.google.com", port=80), resp=True) cs = [ "foo/bar=hello", "foo:bar=world", "foo@bar=fizz", ] for c in cs: f.response.headers["Set-Cookie"] = c sc.response(f) googlekey = list(sc.jar.keys())[0] assert len(sc.jar[googlekey].keys()) == len(cs)
def test_cutspec(): with taddons.context() as tctx: b = mitmproxy.types._CutSpecType() b.parse(tctx.master.commands, mitmproxy.types.CutSpec, "foo,bar") == ["foo", "bar"] assert b.is_valid(tctx.master.commands, mitmproxy.types.CutSpec, 1) is False assert b.is_valid(tctx.master.commands, mitmproxy.types.CutSpec, "foo") is False assert b.is_valid(tctx.master.commands, mitmproxy.types.CutSpec, "request.path") is True assert b.completion(tctx.master.commands, mitmproxy.types.CutSpec, "request.p") == b.valid_prefixes ret = b.completion(tctx.master.commands, mitmproxy.types.CutSpec, "request.port,f") assert ret[0].startswith("request.port,") assert len(ret) == len(b.valid_prefixes)
def test_client_cert_file(self, tdata, client_certs): ta = tlsconfig.TlsConfig() with taddons.context(ta) as tctx: ctx = context.Context(connection.Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), tctx.options) ctx.server.address = ("example.mitmproxy.org", 443) tctx.configure( ta, client_certs=tdata.path(client_certs), ssl_verify_upstream_trusted_ca=tdata.path("mitmproxy/net/data/verificationcerts/trusted-root.crt"), ) tls_start = tls.TlsStartData(ctx.server, context=ctx) ta.tls_start_server(tls_start) tssl_client = tls_start.ssl_conn tssl_server = test_tls.SSLTest(server_side=True) assert self.do_handshake(tssl_client, tssl_server) assert tssl_server.obj.getpeercert()
def test_loader(): with taddons.context() as tctx: l = addonmanager.Loader(tctx.master) l.add_option("custom_option", bool, False, "help") assert "custom_option" in l.master.options # calling this again with the same signature is a no-op. l.add_option("custom_option", bool, False, "help") assert not tctx.master.has_log("Over-riding existing option") # a different signature should emit a warning though. l.add_option("custom_option", bool, True, "help") assert tctx.master.has_log("Over-riding existing option") def cmd(a: str) -> str: return "foo" l.add_command("test.command", cmd)
def test_make_top_layer(self): nl = NextLayer() ctx = MagicMock() with taddons.context(nl) as tctx: tctx.configure(nl, mode="regular") assert isinstance(nl.make_top_layer(ctx), layers.modes.HttpProxy) tctx.configure(nl, mode="transparent") assert isinstance(nl.make_top_layer(ctx), layers.modes.TransparentProxy) tctx.configure(nl, mode="reverse:http://example.com") assert isinstance(nl.make_top_layer(ctx), layers.modes.ReverseProxy) tctx.configure(nl, mode="socks5") with pytest.raises(NotImplementedError): nl.make_top_layer(ctx)
def test_simple(tmpdir): sa = save.Save() with taddons.context(sa) as tctx: p = str(tmpdir.join("foo")) tctx.configure(sa, save_stream_file=p) f = tflow.tflow(resp=True) sa.request(f) sa.response(f) tctx.configure(sa, save_stream_file=None) assert rd(p)[0].response tctx.configure(sa, save_stream_file="+" + p) f = tflow.tflow() sa.request(f) tctx.configure(sa, save_stream_file=None) assert not rd(p)[1].response
def test_script_deletion(self): tdir = tutils.test_data.path("mitmproxy/data/addonscripts/") with open(tdir + "/dummy.py", 'w') as f: f.write("\n") with taddons.context() as tctx: sl = script.ScriptLoader() tctx.master.addons.add(sl) tctx.configure(sl, scripts=[ tutils.test_data.path( "mitmproxy/data/addonscripts/dummy.py") ]) os.remove( tutils.test_data.path("mitmproxy/data/addonscripts/dummy.py")) tctx.invoke(sl, "tick") assert not tctx.options.scripts assert not sl.addons
def test_simple(self): sc = script.ScriptLoader() with taddons.context(loadcore=False) as tctx: tctx.master.addons.add(sc) sc.running() assert len(tctx.master.addons) == 1 tctx.master.options.update( scripts = [ tutils.test_data.path( "mitmproxy/data/addonscripts/recorder/recorder.py" ) ] ) assert len(tctx.master.addons) == 1 assert len(sc.addons) == 1 tctx.master.options.update(scripts = []) assert len(tctx.master.addons) == 1 assert len(sc.addons) == 0
async def test_load(tmpdir): path = str(tmpdir.join("path")) v = view.View() with taddons.context() as tctx: tctx.master.addons.add(v) tdump(path, [tflow.tflow(resp=True), tflow.tflow(resp=True)]) v.load_file(path) assert len(v) == 2 v.load_file(path) assert len(v) == 4 try: v.load_file("nonexistent_file_path") except OSError: assert False with open(path, "wb") as f: f.write(b"invalidflows") v.load_file(path) assert await tctx.master.await_log("Invalid data format.")
def test_configure(): v = view.View() with taddons.context(options=Options()) as tctx: tctx.configure(v, filter="~q") tutils.raises("invalid interception filter", tctx.configure, v, filter="~~") tctx.configure(v, order="method") tutils.raises("unknown flow order", tctx.configure, v, order="no") tctx.configure(v, order_reversed=True) tctx.configure(v, order=None) tctx.configure(v, focus_follow=True) assert v.focus_follow
def test_save_command(tmpdir): sa = save.Save() with taddons.context() as tctx: p = str(tmpdir.join("foo")) sa.save([tflow.tflow(resp=True)], p) assert len(rd(p)) == 1 sa.save([tflow.tflow(resp=True)], p) assert len(rd(p)) == 1 sa.save([tflow.tflow(resp=True)], "+" + p) assert len(rd(p)) == 2 with pytest.raises(exceptions.CommandError): sa.save([tflow.tflow(resp=True)], str(tmpdir)) v = view.View() tctx.master.addons.add(v) tctx.master.addons.add(sa) tctx.master.commands.execute("save.file @shown %s" % p)
def test_create_proxy_server_ssl_conn_insecure(self): ta = tlsconfig.TlsConfig() with taddons.context(ta) as tctx: ctx = context.Context( context.Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), tctx.options) ctx.server.address = ("example.mitmproxy.org", 443) tctx.configure(ta, ssl_verify_upstream_trusted_ca=None, ssl_insecure=True, http2=False, ciphers_server="ALL") tls_start = tls.TlsStartData(ctx.server, context=ctx) ta.tls_start(tls_start) tssl_client = tls_start.ssl_conn tssl_server = test_tls.SSLTest(server_side=True) assert self.do_handshake(tssl_client, tssl_server)
def test_hash(): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: tctx.configure(s) r = tflow.tflow() r2 = tflow.tflow() assert s._hash(r) assert s._hash(r) == s._hash(r2) r.request.headers["foo"] = "bar" assert s._hash(r) == s._hash(r2) r.request.path = "voing" assert s._hash(r) != s._hash(r2) r.request.path = "path?blank_value" r2.request.path = "path?" assert s._hash(r) != s._hash(r2)
def test_create_proxy_server_ssl_conn_verify_failed(self): ta = tlsconfig.TlsConfig() with taddons.context(ta) as tctx: ctx = context.Context( context.Client(("client", 1234), ("127.0.0.1", 8080), 1605699329), tctx.options) ctx.client.alpn_offers = [b"h2"] ctx.client.cipher_list = [ "TLS_AES_256_GCM_SHA384", "ECDHE-RSA-AES128-SHA" ] ctx.server.address = ("example.mitmproxy.org", 443) tls_start = tls.TlsStartData(ctx.server, context=ctx) ta.tls_start(tls_start) tssl_client = tls_start.ssl_conn tssl_server = test_tls.SSLTest(server_side=True) with pytest.raises(SSL.Error, match="certificate verify failed"): assert self.do_handshake(tssl_client, tssl_server)
def test_cut_clip(): v = view.View() c = cut.Cut() with taddons.context() as tctx: tctx.master.addons.add(v, c) v.add([tflow.tflow(resp=True)]) with mock.patch('pyperclip.copy') as pc: tctx.command(c.clip, "@all", "request.method") assert pc.called with mock.patch('pyperclip.copy') as pc: tctx.command(c.clip, "@all", "request.content") assert pc.called with mock.patch('pyperclip.copy') as pc: tctx.command(c.clip, "@all", "request.method,request.content") assert pc.called
def test_simple(self): sc = stickycookie.StickyCookie() with taddons.context() as tctx: tctx.configure(sc, stickycookie=".*") f = tflow.tflow(resp=True) f.response.headers["set-cookie"] = "foo=bar" sc.request(f) f.reply.acked = False sc.response(f) assert sc.jar assert "cookie" not in f.request.headers f = f.copy() f.reply.acked = False sc.request(f) assert f.request.headers["cookie"] == "foo=bar"
def test_configure(): up = proxyauth.ProxyAuth() with taddons.context() as ctx: with pytest.raises(exceptions.OptionsError): ctx.configure(up, proxyauth="foo") ctx.configure(up, proxyauth="foo:bar") assert up.singleuser == ["foo", "bar"] ctx.configure(up, proxyauth=None) assert up.singleuser is None ctx.configure(up, proxyauth="any") assert up.nonanonymous ctx.configure(up, proxyauth=None) assert not up.nonanonymous with pytest.raises(exceptions.OptionsError): ctx.configure( up, proxyauth= "@" + tutils.test_data.path("mitmproxy/net/data/server.crt") ) with pytest.raises(exceptions.OptionsError): ctx.configure(up, proxyauth="@nonexistent") ctx.configure( up, proxyauth= "@" + tutils.test_data.path( "mitmproxy/net/data/htpasswd" ) ) assert up.htpasswd assert up.htpasswd.check_password("test", "test") assert not up.htpasswd.check_password("test", "foo") ctx.configure(up, proxyauth=None) assert not up.htpasswd with pytest.raises(exceptions.OptionsError): ctx.configure(up, proxyauth="any", mode="transparent") with pytest.raises(exceptions.OptionsError): ctx.configure(up, proxyauth="any", mode="socks5") ctx.configure(up, mode="regular") assert up.mode == "regular"
async def test_read(self, tmpdir, data, corrupt_data): rf = readfile.ReadFile() with taddons.context(rf) as tctx: assert not rf.reading() tf = tmpdir.join("tfile") with mock.patch('mitmproxy.master.Master.load_flow') as mck: tf.write(data.getvalue()) tctx.configure(rf, rfile=str(tf), readfile_filter=".*") mck.assert_not_awaited() rf.running() await asyncio.sleep(0) mck.assert_awaited() tf.write(corrupt_data.getvalue()) tctx.configure(rf, rfile=str(tf)) rf.running() assert await tctx.master.await_log("corrupted")
async def test_loader(): with taddons.context() as tctx: with mock.patch("mitmproxy.ctx.log.warn") as warn: l = addonmanager.Loader(tctx.master) l.add_option("custom_option", bool, False, "help") assert "custom_option" in l.master.options # calling this again with the same signature is a no-op. l.add_option("custom_option", bool, False, "help") assert not warn.called # a different signature should emit a warning though. l.add_option("custom_option", bool, True, "help") assert warn.called def cmd(a: str) -> str: return "foo" l.add_command("test.command", cmd)
def test_order(): v = view.View() with taddons.context() as tctx: v.request(tft(method="get", start=1)) v.request(tft(method="put", start=2)) v.request(tft(method="get", start=3)) v.request(tft(method="put", start=4)) assert [i.request.timestamp_start for i in v] == [1, 2, 3, 4] tctx.configure(v, view_order="method") assert [i.request.method for i in v] == ["GET", "GET", "PUT", "PUT"] v.set_reversed(True) assert [i.request.method for i in v] == ["PUT", "PUT", "GET", "GET"] tctx.configure(v, view_order="time") assert [i.request.timestamp_start for i in v] == [4, 3, 2, 1] v.set_reversed(False) assert [i.request.timestamp_start for i in v] == [1, 2, 3, 4]
def test_simple(self): r = replace.Replace() with taddons.context() as tctx: tctx.configure( r, replacements=[ "/~q/foo/bar", "/~s/foo/bar", ] ) f = tflow.tflow() f.request.content = b"foo" r.request(f) assert f.request.content == b"bar" f = tflow.tflow(resp=True) f.response.content = b"foo" r.response(f) assert f.response.content == b"bar"
def test_ignore_params(): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: tctx.configure( s, server_replay_ignore_params=["param1", "param2"] ) r = tflow.tflow(resp=True) r.request.path = "/test?param1=1" r2 = tflow.tflow(resp=True) r2.request.path = "/test" assert s._hash(r) == s._hash(r2) r2.request.path = "/test?param1=2" assert s._hash(r) == s._hash(r2) r2.request.path = "/test?param2=1" assert s._hash(r) == s._hash(r2) r2.request.path = "/test?param3=2" assert not s._hash(r) == s._hash(r2)
def test_export(tmpdir): f = str(tmpdir.join("path")) e = export.Export() with taddons.context(): assert e.formats() == ["curl", "httpie", "raw"] with pytest.raises(exceptions.CommandError): e.file("nonexistent", tflow.tflow(resp=True), f) e.file("raw", tflow.tflow(resp=True), f) assert qr(f) os.unlink(f) e.file("curl", tflow.tflow(resp=True), f) assert qr(f) os.unlink(f) e.file("httpie", tflow.tflow(resp=True), f) assert qr(f) os.unlink(f)
def test_ignore_payload_params_other_content_type(): s = serverplayback.ServerPlayback() with taddons.context(s) as tctx: tctx.configure( s, server_replay_ignore_content=False, server_replay_ignore_payload_params=["param1", "param2"]) r = tflow.tflow(resp=True) r.request.headers["Content-Type"] = "application/json" r.request.content = b'{"param1":"1"}' r2 = tflow.tflow(resp=True) r2.request.headers["Content-Type"] = "application/json" r2.request.content = b'{"param1":"1"}' # same content assert s._hash(r) == s._hash(r2) # distint content (note only x-www-form-urlencoded payload is analysed) r2.request.content = b'{"param1":"2"}' assert not s._hash(r) == s._hash(r2)
def test_simple(): sa = streamfile.StreamFile() with taddons.context() as tctx: with tutils.tmpdir() as tdir: p = os.path.join(tdir, "foo") tctx.configure(sa, streamfile=p) f = tflow.tflow(resp=True) sa.request(f) sa.response(f) tctx.configure(sa, streamfile=None) assert rd(p)[0].response tctx.configure(sa, streamfile=p, streamfile_append=True) f = tflow.tflow() sa.request(f) tctx.configure(sa, streamfile=None) assert not rd(p)[1].response
async def test_allowremote(allow_remote, ip, should_be_killed): ar = allowremote.AllowRemote() up = proxyauth.ProxyAuth() with taddons.context(ar, up) as tctx: tctx.options.allow_remote = allow_remote with mock.patch('mitmproxy.proxy.protocol.base.Layer') as layer: layer.client_conn.address = (ip, 12345) ar.clientconnect(layer) if should_be_killed: assert await tctx.master.await_log("Client connection was killed", "warn") else: assert tctx.master.logs == [] tctx.master.clear() tctx.options.proxyauth = "any" ar.clientconnect(layer) assert tctx.master.logs == []
def test_simple(): sa = core_option_validation.CoreOptionValidation() with taddons.context() as tctx: with pytest.raises(exceptions.OptionsError): tctx.configure(sa, body_size_limit = "invalid") tctx.configure(sa, body_size_limit = "1m") assert tctx.options._processed["body_size_limit"] with pytest.raises(exceptions.OptionsError, match="mutually exclusive"): tctx.configure( sa, add_upstream_certs_to_client_chain = True, upstream_cert = False ) with pytest.raises(exceptions.OptionsError, match="Invalid mode"): tctx.configure( sa, mode = "Flibble" )