Compare commits

..

10 Commits

Author SHA1 Message Date
Maximilian Hils
c7a96b2fb1 always show error messages 2014-11-15 00:52:26 +01:00
Aldo Cortesi
4c2e87638a Changelog, plus fix date of previous release 2014-11-15 12:49:21 +13:00
Maximilian Hils
afc6ef99ea bump version 2014-11-14 16:18:05 +01:00
Maximilian Hils
be449b7129 fix #409 2014-11-14 16:13:45 +01:00
Maximilian Hils
0c52b4e3b9 handle script hooks in replay, fix tests, fix #402 2014-11-14 00:26:22 +01:00
Maximilian Hils
9b5a8af12d fix grideditor bug 2014-11-14 00:21:47 +01:00
Maximilian Hils
8cbb67ac70 docs++ 2014-11-13 23:03:06 +01:00
Maximilian Hils
a325ae638b fix tests 2014-11-11 13:09:05 +01:00
Maximilian Hils
2335d00c1c Merge branch 'master' of github.com:mitmproxy/mitmproxy 2014-11-11 12:30:56 +01:00
Maximilian Hils
f19ee74b99 be more explicit about requirements 2014-11-11 12:30:51 +01:00
11 changed files with 87 additions and 50 deletions

View File

@@ -1,5 +1,10 @@
23 October 2014: mitmproxy 0.11:
15 November 2014: mitmproxy 0.11.1:
* Bug fixes: connection leaks some crashes
7 November 2014: mitmproxy 0.11:
* Performance improvements for mitmproxy console

View File

@@ -71,6 +71,15 @@ For example, you can generate a certificate in this format using these instructi
</pre>
Using a custom certificate authority
------------------------------------
By default, mitmproxy will (generate and) use <samp>~/.mitmproxy/mitmproxy-ca.pem</samp> as the default certificate
authority to generate certificates for all domains for which no custom certificate is provided (see above).
You can use your own certificate authority by passing the <kbd>--confdir</kbd> option to mitmproxy.
mitmproxy will then look for <samp>mitmproxy-ca.pem</samp> in the specified directory. If no such file exists,
it will be generated automatically.
Installing the mitmproxy CA
---------------------------

View File

@@ -1050,7 +1050,7 @@ class ConsoleMaster(flow.FlowMaster):
self.eventlist[:] = []
def add_event(self, e, level="info"):
needed = dict(error=1, info=1, debug=2).get(level, 1)
needed = dict(error=0, info=1, debug=2).get(level, 1)
if self.options.verbosity < needed:
return

View File

@@ -129,6 +129,8 @@ class GridWalker(urwid.ListWalker):
if emsg:
self.editor.master.statusbar.message(emsg, 1000)
errors.add(self.focus_col)
else:
errors.discard(self.focus_col)
row = list(self.lst[self.focus][0])
row[self.focus_col] = val

View File

@@ -155,7 +155,7 @@ class DumpMaster(flow.FlowMaster):
return flows
def add_event(self, e, level="info"):
needed = dict(error=1, info=1, debug=2).get(level, 1)
needed = dict(error=0, info=1, debug=2).get(level, 1)
if self.o.verbosity >= needed:
print >> self.outfile, e
self.outfile.flush()

View File

@@ -169,6 +169,7 @@ class ClientPlaybackState:
def __init__(self, flows, exit):
self.flows, self.exit = flows, exit
self.current = None
self.testing = False # Disables actual replay for testing.
def count(self):
return len(self.flows)
@@ -186,19 +187,16 @@ class ClientPlaybackState:
if flow is self.current:
self.current = None
def tick(self, master, testing=False):
"""
testing: Disables actual replay for testing.
"""
def tick(self, master):
if self.flows and not self.current:
n = self.flows.pop(0)
n.response = None
n.reply = controller.DummyReply()
self.current = master.handle_request(n)
if not testing and not self.current.response:
master.replay_request(self.current) # pragma: no cover
elif self.current.response:
master.handle_response(self.current)
self.current = self.flows.pop(0).copy()
if not self.testing:
master.replay_request(self.current)
else:
self.current.reply = controller.DummyReply()
master.handle_request(self.current)
if self.current.response:
master.handle_response(self.current)
class ServerPlaybackState:
@@ -371,6 +369,8 @@ class State(object):
"""
Add a request to the state. Returns the matching flow.
"""
if flow in self._flow_list: # catch flow replay
return flow
self._flow_list.append(flow)
if flow.match(self._limit):
self.view.append(flow)

View File

@@ -1040,7 +1040,7 @@ class HTTPHandler(ProtocolHandler):
# inline script to set flow.stream = True
flow = self.c.channel.ask("responseheaders", flow)
if flow == KILL:
raise KillSignal
raise KillSignal()
else:
# now get the rest of the request body, if body still needs to be
# read but not streaming this response
@@ -1085,7 +1085,7 @@ class HTTPHandler(ProtocolHandler):
self.process_server_address(flow) # The inline script may have changed request.host
if request_reply is None or request_reply == KILL:
return False
raise KillSignal()
if isinstance(request_reply, HTTPResponse):
flow.response = request_reply
@@ -1099,7 +1099,7 @@ class HTTPHandler(ProtocolHandler):
self.c.log("response", "debug", [flow.response._assemble_first_line()])
response_reply = self.c.channel.ask("response", flow)
if response_reply is None or response_reply == KILL:
return False
raise KillSignal()
self.send_response_to_client(flow)
@@ -1140,7 +1140,6 @@ class HTTPHandler(ProtocolHandler):
self.handle_error(e, flow)
except KillSignal:
self.c.log("Connection killed", "info")
flow.live = None
finally:
flow.live = None # Connection is not live anymore.
return False
@@ -1437,32 +1436,43 @@ class RequestReplayThread(threading.Thread):
r = self.flow.request
form_out_backup = r.form_out
try:
# In all modes, we directly connect to the server displayed
if self.config.mode == "upstream":
server_address = self.config.mode.get_upstream_server(self.flow.client_conn)[2:]
server = ServerConnection(server_address)
server.connect()
if r.scheme == "https":
send_connect_request(server, r.host, r.port)
server.establish_ssl(self.config.clientcerts, sni=self.flow.server_conn.sni)
r.form_out = "relative"
else:
r.form_out = "absolute"
self.flow.response = None
request_reply = self.channel.ask("request", self.flow)
if request_reply is None or request_reply == KILL:
raise KillSignal()
elif isinstance(request_reply, HTTPResponse):
self.flow.response = request_reply
else:
server_address = (r.host, r.port)
server = ServerConnection(server_address)
server.connect()
if r.scheme == "https":
server.establish_ssl(self.config.clientcerts, sni=self.flow.server_conn.sni)
r.form_out = "relative"
# In all modes, we directly connect to the server displayed
if self.config.mode == "upstream":
server_address = self.config.mode.get_upstream_server(self.flow.client_conn)[2:]
server = ServerConnection(server_address)
server.connect()
if r.scheme == "https":
send_connect_request(server, r.host, r.port)
server.establish_ssl(self.config.clientcerts, sni=self.flow.server_conn.sni)
r.form_out = "relative"
else:
r.form_out = "absolute"
else:
server_address = (r.host, r.port)
server = ServerConnection(server_address)
server.connect()
if r.scheme == "https":
server.establish_ssl(self.config.clientcerts, sni=self.flow.server_conn.sni)
r.form_out = "relative"
server.send(r.assemble())
self.flow.server_conn = server
self.flow.response = HTTPResponse.from_stream(server.rfile, r.method,
body_size_limit=self.config.body_size_limit)
self.channel.ask("response", self.flow)
except (proxy.ProxyError, http.HttpError, tcp.NetLibError), v:
server.send(r.assemble())
self.flow.server_conn = server
self.flow.response = HTTPResponse.from_stream(server.rfile, r.method,
body_size_limit=self.config.body_size_limit)
response_reply = self.channel.ask("response", self.flow)
if response_reply is None or response_reply == KILL:
raise KillSignal()
except (proxy.ProxyError, http.HttpError, tcp.NetLibError) as v:
self.flow.error = Error(repr(v))
self.channel.ask("error", self.flow)
except KillSignal:
self.channel.tell("log", proxy.Log("Connection killed", "info"))
finally:
r.form_out = form_out_backup

View File

@@ -99,7 +99,6 @@ class ConnectionHandler:
# Delegate handling to the protocol handler
protocol_handler(self.conntype)(self, **conn_kwargs).handle_messages()
self.del_server_connection()
self.log("clientdisconnect", "info")
self.channel.tell("clientdisconnect", self)
@@ -112,6 +111,10 @@ class ConnectionHandler:
print >> sys.stderr, traceback.format_exc()
print >> sys.stderr, "mitmproxy has crashed!"
print >> sys.stderr, "Please lodge a bug report at: https://github.com/mitmproxy/mitmproxy"
finally:
# Make sure that we close the server connection in any case.
# The client connection is closed by the ProxyServer and does not have be handled here.
self.del_server_connection()
def del_server_connection(self):
"""
@@ -119,6 +122,7 @@ class ConnectionHandler:
"""
if self.server_conn and self.server_conn.connection:
self.server_conn.finish()
self.server_conn.close()
self.log("serverdisconnect", "debug", ["%s:%s" % (self.server_conn.address.host,
self.server_conn.address.port)])
self.channel.tell("serverdisconnect", self)

View File

@@ -1,5 +1,9 @@
IVERSION = (0, 11)
IVERSION = (0, 11, 1)
VERSION = ".".join(str(i) for i in IVERSION)
MINORVERSION = ".".join(str(i) for i in IVERSION[:2])
NAME = "mitmproxy"
NAMEVERSION = NAME + " " + VERSION
NEXT_MINORVERSION = list(IVERSION)
NEXT_MINORVERSION[1] += 1
NEXT_MINORVERSION = ".".join(str(i) for i in NEXT_MINORVERSION[:2])

View File

@@ -16,7 +16,7 @@ if os.name != "nt":
scripts.append("mitmproxy")
deps = {
"netlib>=%s" % version.MINORVERSION,
"netlib>=%s, <%s" % (version.MINORVERSION, version.NEXT_MINORVERSION),
"pyasn1>0.1.2",
"pyOpenSSL>=0.14",
"Flask>=0.10.1",
@@ -72,7 +72,7 @@ setup(
"nose>=1.3.0",
"nose-cov>=1.6",
"coveralls>=0.4.1",
"pathod>=%s" % version.MINORVERSION
"pathod>=%s, <%s" % (version.MINORVERSION, version.NEXT_MINORVERSION)
],
'contentviews': [
"pyamf>=0.6.1",

View File

@@ -86,19 +86,20 @@ class TestClientPlaybackState:
fm = flow.FlowMaster(None, s)
fm.start_client_playback([first, tutils.tflow()], True)
c = fm.client_playback
c.testing = True
assert not c.done()
assert not s.flow_count()
assert c.count() == 2
c.tick(fm, testing=True)
c.tick(fm)
assert s.flow_count()
assert c.count() == 1
c.tick(fm, testing=True)
c.tick(fm)
assert c.count() == 1
c.clear(c.current)
c.tick(fm, testing=True)
c.tick(fm)
assert c.count() == 0
c.clear(c.current)
assert c.done()
@@ -692,9 +693,11 @@ class TestFlowMaster:
f = tutils.tflow(resp=True)
pb = [tutils.tflow(resp=True), f]
fm = flow.FlowMaster(None, s)
fm = flow.FlowMaster(DummyServer(ProxyConfig()), s)
assert not fm.start_server_playback(pb, False, [], False, False, None, False)
assert not fm.start_client_playback(pb, False)
fm.client_playback.testing = True
q = Queue.Queue()
assert not fm.state.flow_count()