aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2011-02-03 13:30:47 +1300
committerAldo Cortesi <aldo@nullcube.com>2011-02-03 13:30:47 +1300
commit6c89749f0a0c77e3a56a68df8709daf9c9f2f33c (patch)
tree2c12a17a18f5215124da887a3b0c465fd0c910b9 /libmproxy
parent673ff01acc07c0aa04c5a37f745343cebc34c64b (diff)
downloadmitmproxy-6c89749f0a0c77e3a56a68df8709daf9c9f2f33c.tar.gz
mitmproxy-6c89749f0a0c77e3a56a68df8709daf9c9f2f33c.tar.bz2
mitmproxy-6c89749f0a0c77e3a56a68df8709daf9c9f2f33c.zip
Add timestamps to flows.
For now, these are only displayed on the connection view screen, with second granularity.
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/console.py24
-rw-r--r--libmproxy/proxy.py21
-rw-r--r--libmproxy/utils.py8
3 files changed, 42 insertions, 11 deletions
diff --git a/libmproxy/console.py b/libmproxy/console.py
index 8151ccea..eac2823a 100644
--- a/libmproxy/console.py
+++ b/libmproxy/console.py
@@ -44,13 +44,19 @@ def format_keyvals(lst, key="key", val="text", space=5, indent=0):
return ret
-def format_flow(f, focus, padding=3):
+def format_flow(f, focus, extended=False, padding=3):
if not f.request and not f.response:
txt = [
("title", " Connection from %s..."%(f.connection.address)),
]
else:
+ if extended:
+ ts = ("highlight", utils.format_timestamp(f.request.timestamp))
+ else:
+ ts = ""
+
txt = [
+ ts,
("ack", "!") if f.intercepting and not f.request.acked else " ",
("method", f.request.method),
" ",
@@ -60,7 +66,16 @@ def format_flow(f, focus, padding=3):
),
]
if f.response or f.error or f.is_replay():
- txt.append("\n" + " "*(padding+2))
+
+ tsr = f.response or f.error
+ if extended and tsr:
+ ts = ("highlight", utils.format_timestamp(tsr.timestamp))
+ else:
+ ts = ""
+
+ txt.append("\n")
+ txt.append(("text", ts))
+ txt.append(" "*(padding+2))
met = ""
if f.is_replay():
txt.append(("method", "[replay] "))
@@ -198,11 +213,11 @@ class ConnectionListView(urwid.ListWalker):
class ConnectionViewHeader(WWrap):
def __init__(self, master, f):
self.master, self.flow = master, f
- self.w = urwid.Text(format_flow(f, False, padding=0))
+ self.w = urwid.Text(format_flow(f, False, extended=True, padding=0))
def refresh_connection(self, f):
if f == self.flow:
- self.w = urwid.Text(format_flow(f, False, padding=0))
+ self.w = urwid.Text(format_flow(f, False, extended=True, padding=0))
VIEW_BODY_RAW = 0
@@ -810,6 +825,7 @@ class ConsoleMaster(controller.Master):
('error', 'light red', 'default'),
('header', 'dark cyan', 'default'),
('heading', 'white', 'dark blue'),
+ ('highlight', 'white', 'default'),
('inactive', 'dark gray', 'default'),
('ack', 'light red', 'default'),
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index 00b9e0ba..5110a71a 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -84,10 +84,11 @@ def parse_proxy_request(request):
class Request(controller.Msg):
FMT = '%s %s HTTP/1.0\r\n%s\r\n%s'
- def __init__(self, connection, host, port, scheme, method, path, headers, content):
+ def __init__(self, connection, host, port, scheme, method, path, headers, content, timestamp=None):
self.connection = connection
self.host, self.port, self.scheme = host, port, scheme
self.method, self.path, self.headers, self.content = method, path, headers, content
+ self.timestamp = timestamp or time.time()
controller.Msg.__init__(self)
def get_state(self):
@@ -98,7 +99,8 @@ class Request(controller.Msg):
method = self.method,
path = self.path,
headers = self.headers.get_state(),
- content = self.content
+ content = self.content,
+ timestamp = self.timestamp,
)
@classmethod
@@ -111,7 +113,8 @@ class Request(controller.Msg):
state["method"],
state["path"],
utils.Headers.from_state(state["headers"]),
- state["content"]
+ state["content"],
+ state["timestamp"]
)
def __eq__(self, other):
@@ -159,10 +162,11 @@ class Request(controller.Msg):
class Response(controller.Msg):
FMT = '%s\r\n%s\r\n%s'
- def __init__(self, request, code, proto, msg, headers, content):
+ def __init__(self, request, code, proto, msg, headers, content, timestamp=None):
self.request = request
self.code, self.proto, self.msg = code, proto, msg
self.headers, self.content = headers, content
+ self.timestamp = timestamp or time.time()
controller.Msg.__init__(self)
def get_state(self):
@@ -171,6 +175,7 @@ class Response(controller.Msg):
proto = self.proto,
msg = self.msg,
headers = self.headers.get_state(),
+ timestamp = self.timestamp,
content = self.content
)
@@ -182,7 +187,8 @@ class Response(controller.Msg):
state["proto"],
state["msg"],
utils.Headers.from_state(state["headers"]),
- state["content"]
+ state["content"],
+ state["timestamp"],
)
def __eq__(self, other):
@@ -225,8 +231,9 @@ class BrowserConnection(controller.Msg):
class Error(controller.Msg):
- def __init__(self, connection, msg):
+ def __init__(self, connection, msg, timestamp=None):
self.connection, self.msg = connection, msg
+ self.timestamp = timestamp or time.time()
controller.Msg.__init__(self)
def copy(self):
@@ -235,6 +242,7 @@ class Error(controller.Msg):
def get_state(self):
return dict(
msg = self.msg,
+ timestamp = self.timestamp,
)
@classmethod
@@ -242,6 +250,7 @@ class Error(controller.Msg):
return klass(
None,
state["msg"],
+ state["timestamp"],
)
def __eq__(self, other):
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index 7b9d0e32..ee0d9b43 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -13,9 +13,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import re, os, subprocess
+import re, os, subprocess, datetime
from contrib import BeautifulSoup
+
+def format_timestamp(s):
+ d = datetime.datetime.fromtimestamp(s)
+ return d.strftime("%Y-%m-%d %H:%M:%S")
+
+
def isBin(s):
"""
Does this string have any non-ASCII characters?