Add timestamps to flows.

For now, these are only displayed on the connection view screen, with second
granularity.
This commit is contained in:
Aldo Cortesi 2011-02-03 13:30:47 +13:00
parent 673ff01acc
commit 6c89749f0a
6 changed files with 56 additions and 12 deletions

View File

@ -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'),

View File

@ -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):

View File

@ -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?

View File

@ -108,13 +108,18 @@ class uformat_flow(libpry.AutoTree):
assert ('focus', '>> ') not in console.format_flow(f, False)
assert ('focus', '>> ') in console.format_flow(f, True)
assert ('focus', '>> ') not in console.format_flow(f, False, True)
assert ('focus', '>> ') in console.format_flow(f, True, True)
f.response = utils.tresp()
f.request = f.response.request
f.backup()
assert ('method', '[edited] ') in console.format_flow(f, True)
assert ('method', '[edited] ') in console.format_flow(f, True, True)
f.connection = flow.ReplayConnection()
assert ('method', '[replay] ') in console.format_flow(f, True)
assert ('method', '[replay] ') in console.format_flow(f, True, True)
class uPathCompleter(libpry.AutoTree):

View File

@ -267,6 +267,8 @@ class uError(libpry.AutoTree):
state = e.get_state()
assert proxy.Error.from_state(state) == e
assert e.copy()
class uProxyError(libpry.AutoTree):
def test_simple(self):

View File

@ -1,8 +1,13 @@
import textwrap, cStringIO, os
import textwrap, cStringIO, os, time
import libpry
from libmproxy import utils
class uformat_timestamp(libpry.AutoTree):
def test_simple(self):
assert utils.format_timestamp(time.time())
class uisBin(libpry.AutoTree):
def test_simple(self):
assert not utils.isBin("testing\n\r")
@ -234,6 +239,7 @@ class uprettybody(libpry.AutoTree):
tests = [
uformat_timestamp(),
umake_bogus_cert(),
uisBin(),
uhexdump(),