diff options
-rw-r--r-- | issue_template.md | 4 | ||||
-rw-r--r-- | mitmproxy/console/common.py | 8 | ||||
-rw-r--r-- | mitmproxy/flow.py | 19 | ||||
-rw-r--r-- | netlib/odict.py | 81 | ||||
-rw-r--r-- | test/netlib/test_odict.py | 10 | ||||
-rw-r--r-- | test/pathod/test_pathoc.py | 2 | ||||
-rw-r--r-- | test/pathod/test_pathod.py | 7 |
7 files changed, 58 insertions, 73 deletions
diff --git a/issue_template.md b/issue_template.md index 3f9be788..08d390e4 100644 --- a/issue_template.md +++ b/issue_template.md @@ -10,10 +10,10 @@ ##### What went wrong? -##### Any other comments? +##### Any other comments? What have you tried so far? --- Mitmproxy Version: -Operating System:
\ No newline at end of file +Operating System: diff --git a/mitmproxy/console/common.py b/mitmproxy/console/common.py index 4e472fb6..25658dfa 100644 --- a/mitmproxy/console/common.py +++ b/mitmproxy/console/common.py @@ -154,7 +154,7 @@ def raw_format_flow(f, focus, extended): if f["intercepted"] and not f["acked"]: uc = "intercept" - elif f["resp_code"] or f["err_msg"]: + elif "resp_code" in f or "err_msg" in f: uc = "text" else: uc = "title" @@ -173,7 +173,7 @@ def raw_format_flow(f, focus, extended): ("fixed", preamble, urwid.Text("")) ) - if f["resp_code"]: + if "resp_code" in f: codes = { 2: "code_200", 3: "code_300", @@ -185,6 +185,8 @@ def raw_format_flow(f, focus, extended): if f["resp_is_replay"]: resp.append(fcol(SYMBOL_REPLAY, "replay")) resp.append(fcol(f["resp_code"], ccol)) + if extended: + resp.append(fcol(f["resp_reason"], ccol)) if f["intercepted"] and f["resp_code"] and not f["acked"]: rc = "intercept" else: @@ -412,7 +414,6 @@ def format_flow(f, focus, extended=False, hostheader=False, marked=False): req_http_version = f.request.http_version, err_msg = f.error.msg if f.error else None, - resp_code = f.response.status_code if f.response else None, marked = marked, ) @@ -430,6 +431,7 @@ def format_flow(f, focus, extended=False, hostheader=False, marked=False): d.update(dict( resp_code = f.response.status_code, + resp_reason = f.response.reason, resp_is_replay = f.response.is_replay, resp_clen = contentdesc, roundtrip = roundtrip, diff --git a/mitmproxy/flow.py b/mitmproxy/flow.py index 647ebf68..a9018e16 100644 --- a/mitmproxy/flow.py +++ b/mitmproxy/flow.py @@ -13,6 +13,8 @@ from six.moves import http_cookies, http_cookiejar, urllib import os import re +from typing import List, Optional, Set + from netlib import wsgi, odict from netlib.exceptions import HttpException from netlib.http import Headers, http1, cookies @@ -376,8 +378,11 @@ class StickyAuthState: f.request.headers["authorization"] = self.hosts[host] +@six.add_metaclass(ABCMeta) class FlowList(object): - __metaclass__ = ABCMeta + + def __init__(self): + self._list = [] # type: List[Flow] def __iter__(self): return iter(self._list) @@ -416,7 +421,7 @@ class FlowList(object): class FlowView(FlowList): def __init__(self, store, filt=None): - self._list = [] + super(FlowView, self).__init__() if not filt: filt = lambda flow: True self._build(store, filt) @@ -458,7 +463,7 @@ class FlowStore(FlowList): """ def __init__(self): - self._list = [] + super(FlowStore, self).__init__() self._set = set() # Used for O(1) lookups self.views = [] self._recalculate_views() @@ -649,18 +654,18 @@ class FlowMaster(controller.ServerMaster): self.server_playback = None self.client_playback = None self.kill_nonreplay = False - self.scripts = [] + self.scripts = [] # type: List[script.Script] self.pause_scripts = False - self.stickycookie_state = False + self.stickycookie_state = None # type: Optional[StickyCookieState] self.stickycookie_txt = None - self.stickyauth_state = False + self.stickyauth_state = False # type: Optional[StickyAuthState] self.stickyauth_txt = None self.anticache = False self.anticomp = False - self.stream_large_bodies = False + self.stream_large_bodies = None # type: Optional[StreamLargeBodies] self.refresh_server_playback = False self.replacehooks = ReplaceHooks() self.setheaders = SetHeaders() diff --git a/netlib/odict.py b/netlib/odict.py index 461192f7..8a638dab 100644 --- a/netlib/odict.py +++ b/netlib/odict.py @@ -1,5 +1,6 @@ from __future__ import (absolute_import, print_function, division) import copy + import six from .utils import Serializable, safe_subn @@ -27,27 +28,24 @@ class ODict(Serializable): def __iter__(self): return self.lst.__iter__() - def __getitem__(self, k): + def __getitem__(self, key): """ Returns a list of values matching key. """ - ret = [] - k = self._kconv(k) - for i in self.lst: - if self._kconv(i[0]) == k: - ret.append(i[1]) - return ret - def keys(self): - return list(set([self._kconv(i[0]) for i in self.lst])) + key = self._kconv(key) + return [ + v + for k, v in self.lst + if self._kconv(k) == key + ] - def _filter_lst(self, k, lst): - k = self._kconv(k) - new = [] - for i in lst: - if self._kconv(i[0]) != k: - new.append(i) - return new + def keys(self): + return list( + set( + self._kconv(k) for k, _ in self.lst + ) + ) def __len__(self): """ @@ -81,14 +79,19 @@ class ODict(Serializable): """ Delete all items matching k. """ - self.lst = self._filter_lst(k, self.lst) - - def __contains__(self, k): k = self._kconv(k) - for i in self.lst: - if self._kconv(i[0]) == k: - return True - return False + self.lst = [ + i + for i in self.lst + if self._kconv(i[0]) != k + ] + + def __contains__(self, key): + key = self._kconv(key) + return any( + self._kconv(k) == key + for k, _ in self.lst + ) def add(self, key, value, prepend=False): if prepend: @@ -127,40 +130,24 @@ class ODict(Serializable): def __repr__(self): return repr(self.lst) - def in_any(self, key, value, caseless=False): - """ - Do any of the values matching key contain value? - - If caseless is true, value comparison is case-insensitive. - """ - if caseless: - value = value.lower() - for i in self[key]: - if caseless: - i = i.lower() - if value in i: - return True - return False - def replace(self, pattern, repl, *args, **kwargs): """ Replaces a regular expression pattern with repl in both keys and - values. Encoded content will be decoded before replacement, and - re-encoded afterwards. + values. Returns the number of replacements made. """ - nlst, count = [], 0 - for i in self.lst: - k, c = safe_subn(pattern, repl, i[0], *args, **kwargs) + new, count = [], 0 + for k, v in self.lst: + k, c = safe_subn(pattern, repl, k, *args, **kwargs) count += c - v, c = safe_subn(pattern, repl, i[1], *args, **kwargs) + v, c = safe_subn(pattern, repl, v, *args, **kwargs) count += c - nlst.append([k, v]) - self.lst = nlst + new.append([k, v]) + self.lst = new return count - # Implement the StateObject protocol from mitmproxy + # Implement Serializable def get_state(self): return [tuple(i) for i in self.lst] diff --git a/test/netlib/test_odict.py b/test/netlib/test_odict.py index f0985ef6..b6fd6401 100644 --- a/test/netlib/test_odict.py +++ b/test/netlib/test_odict.py @@ -27,16 +27,6 @@ class TestODict(object): b.set_state(state) assert b == od - def test_in_any(self): - od = odict.ODict() - od["one"] = ["atwoa", "athreea"] - assert od.in_any("one", "two") - assert od.in_any("one", "three") - assert not od.in_any("one", "four") - assert not od.in_any("nonexistent", "foo") - assert not od.in_any("one", "TWO") - assert od.in_any("one", "TWO", True) - def test_iter(self): od = odict.ODict() assert not [i for i in od] diff --git a/test/pathod/test_pathoc.py b/test/pathod/test_pathoc.py index 8d0f92ac..4e8c89c5 100644 --- a/test/pathod/test_pathoc.py +++ b/test/pathod/test_pathoc.py @@ -211,7 +211,7 @@ class TestDaemon(_TestDaemon): c.stop() @skip_windows - @pytest.mark.xfail + @pytest.mark.skip(reason="race condition") def test_wait_finish(self): c = pathoc.Pathoc( ("127.0.0.1", self.d.port), diff --git a/test/pathod/test_pathod.py b/test/pathod/test_pathod.py index 1718cc0b..05a3962e 100644 --- a/test/pathod/test_pathod.py +++ b/test/pathod/test_pathod.py @@ -129,7 +129,7 @@ class CommonTests(tutils.DaemonTests): l = self.d.last_log() # FIXME: Other binary data elements - @pytest.mark.skip + @pytest.mark.skip(reason="race condition") def test_sizelimit(self): r = self.get("200:b@1g") assert r.status_code == 800 @@ -143,7 +143,7 @@ class CommonTests(tutils.DaemonTests): def test_info(self): assert tuple(self.d.info()["version"]) == version.IVERSION - @pytest.mark.skip + @pytest.mark.skip(reason="race condition") def test_logs(self): assert self.d.clear_log() assert not self.d.last_log() @@ -223,7 +223,7 @@ class CommonTests(tutils.DaemonTests): ) assert r[1].payload == "test" - @pytest.mark.skip + @pytest.mark.skip(reason="race condition") def test_websocket_frame_reflect_error(self): r, _ = self.pathoc( ["ws:/p/", "wf:-mask:knone:f'wf:b@10':i13,'a'"], @@ -233,6 +233,7 @@ class CommonTests(tutils.DaemonTests): # FIXME: Race Condition? assert "Parse error" in self.d.text_log() + @pytest.mark.skip(reason="race condition") def test_websocket_frame_disconnect_error(self): self.pathoc(["ws:/p/", "wf:b@10:d3"], ws_read_limit=0) assert self.d.last_log() |