aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/addons/streamfile.py2
-rw-r--r--mitmproxy/options.py22
-rw-r--r--mitmproxy/optmanager.py16
-rw-r--r--mitmproxy/tools/console/master.py2
-rw-r--r--mitmproxy/tools/console/options.py41
-rw-r--r--test/mitmproxy/test_optmanager.py7
6 files changed, 53 insertions, 37 deletions
diff --git a/mitmproxy/addons/streamfile.py b/mitmproxy/addons/streamfile.py
index 377f277d..2fc61015 100644
--- a/mitmproxy/addons/streamfile.py
+++ b/mitmproxy/addons/streamfile.py
@@ -23,7 +23,7 @@ class StreamFile:
def configure(self, options, updated):
# We're already streaming - stop the previous stream and restart
if "filtstr" in updated:
- if options.get("filtstr"):
+ if options.filtstr:
self.filt = flowfilter.parse(options.filtstr)
if not self.filt:
raise exceptions.OptionsError(
diff --git a/mitmproxy/options.py b/mitmproxy/options.py
index 8a9385da..bf35cd59 100644
--- a/mitmproxy/options.py
+++ b/mitmproxy/options.py
@@ -30,19 +30,19 @@ class Options(optmanager.OptManager):
app_port: int = APP_PORT,
anticache: bool = False,
anticomp: bool = False,
- client_replay: Sequence[str] = (),
+ client_replay: Sequence[str] = [],
replay_kill_extra: bool = False,
keepserving: bool = True,
no_server: bool = False,
server_replay_nopop: bool = False,
refresh_server_playback: bool = False,
rfile: Optional[str] = None,
- scripts: Sequence[str] = (),
+ scripts: Sequence[str] = [],
showhost: bool = False,
- replacements: Sequence[Tuple[str, str, str]] = (),
- server_replay_use_headers: Sequence[str] = (),
- setheaders: Sequence[Tuple[str, str, str]] = (),
- server_replay: Sequence[str] = (),
+ replacements: Sequence[Tuple[str, str, str]] = [],
+ server_replay_use_headers: Sequence[str] = [],
+ setheaders: Sequence[Tuple[str, str, str]] = [],
+ server_replay: Sequence[str] = [],
stickycookie: Optional[str] = None,
stickyauth: Optional[str] = None,
stream_large_bodies: Optional[int] = None,
@@ -51,8 +51,8 @@ class Options(optmanager.OptManager):
streamfile: Optional[str] = None,
streamfile_append: bool = False,
server_replay_ignore_content: bool = False,
- server_replay_ignore_params: Sequence[str] = (),
- server_replay_ignore_payload_params: Sequence[str] = (),
+ server_replay_ignore_params: Sequence[str] = [],
+ server_replay_ignore_payload_params: Sequence[str] = [],
server_replay_ignore_host: bool = False,
# Proxy options
auth_nonanonymous: bool = False,
@@ -61,12 +61,12 @@ class Options(optmanager.OptManager):
add_upstream_certs_to_client_chain: bool = False,
body_size_limit: Optional[int] = None,
cadir: str = CA_DIR,
- certs: Sequence[Tuple[str, str]] = (),
+ certs: Sequence[Tuple[str, str]] = [],
ciphers_client: str=DEFAULT_CLIENT_CIPHERS,
ciphers_server: Optional[str]=None,
clientcerts: Optional[str] = None,
http2: bool = True,
- ignore_hosts: Sequence[str] = (),
+ ignore_hosts: Sequence[str] = [],
listen_host: str = "",
listen_port: int = LISTEN_PORT,
upstream_bind_address: str = "",
@@ -82,7 +82,7 @@ class Options(optmanager.OptManager):
ssl_insecure: bool = False,
ssl_verify_upstream_trusted_cadir: Optional[str] = None,
ssl_verify_upstream_trusted_ca: Optional[str] = None,
- tcp_hosts: Sequence[str] = ()
+ tcp_hosts: Sequence[str] = []
) -> None:
# We could replace all assignments with clever metaprogramming,
# but type hints are a much more valueable asset.
diff --git a/mitmproxy/optmanager.py b/mitmproxy/optmanager.py
index 0421d4be..56122baa 100644
--- a/mitmproxy/optmanager.py
+++ b/mitmproxy/optmanager.py
@@ -2,6 +2,7 @@ import contextlib
import blinker
import pprint
import inspect
+import copy
from mitmproxy import exceptions
from mitmproxy.utils import typecheck
@@ -21,6 +22,9 @@ class OptManager:
updated. If any handler in the chain raises an exceptions.OptionsError
exception, all changes are rolled back, the exception is suppressed,
and the .errored signal is notified.
+
+ Optmanager always returns a deep copy of options to ensure that
+ mutation doesn't change the option state inadvertently.
"""
_initialized = False
attributes = []
@@ -67,7 +71,7 @@ class OptManager:
def __getattr__(self, attr):
if attr in self._opts:
- return self._opts[attr]
+ return copy.deepcopy(self._opts[attr])
else:
raise AttributeError("No such option: %s" % attr)
@@ -89,9 +93,6 @@ class OptManager:
def keys(self):
return set(self._opts.keys())
- def get(self, k, d=None):
- return self._opts.get(k, d)
-
def reset(self):
"""
Restore defaults for all options.
@@ -132,6 +133,13 @@ class OptManager:
setattr(self, attr, not getattr(self, attr))
return toggle
+ def has_changed(self, option):
+ """
+ Has the option changed from the default?
+ """
+ if getattr(self, option) != self._defaults[option]:
+ return True
+
def __repr__(self):
options = pprint.pformat(self._opts, indent=4).strip(" {}")
if "\n" in options:
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
index 5d0e0ef4..455824d3 100644
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -47,7 +47,7 @@ class Options(mitmproxy.options.Options):
focus_follow: bool = False,
intercept: Optional[str] = None,
filter: Optional[str] = None,
- palette: Optional[str] = None,
+ palette: Optional[str] = palettes.DEFAULT,
palette_transparent: bool = False,
no_mouse: bool = False,
order: Optional[str] = None,
diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py
index 9d698161..94483b3d 100644
--- a/mitmproxy/tools/console/options.py
+++ b/mitmproxy/tools/console/options.py
@@ -3,7 +3,6 @@ import urwid
from mitmproxy import contentviews
from mitmproxy.tools.console import common
from mitmproxy.tools.console import grideditor
-from mitmproxy.tools.console import palettes
from mitmproxy.tools.console import select
from mitmproxy.tools.console import signals
@@ -26,6 +25,12 @@ def _mkhelp():
help_context = _mkhelp()
+def checker(opt, options):
+ def _check():
+ return options.has_changed(opt)
+ return _check
+
+
class Options(urwid.WidgetWrap):
def __init__(self, master):
@@ -36,25 +41,25 @@ class Options(urwid.WidgetWrap):
select.Option(
"Header Set Patterns",
"H",
- lambda: len(master.options.setheaders),
+ checker("setheaders", master.options),
self.setheaders
),
select.Option(
"Ignore Patterns",
"I",
- lambda: master.options.ignore_hosts,
+ checker("ignore_hosts", master.options),
self.ignore_hosts
),
select.Option(
"Replacement Patterns",
"R",
- lambda: len(master.options.replacements),
+ checker("replacements", master.options),
self.replacepatterns
),
select.Option(
"Scripts",
"S",
- lambda: master.options.scripts,
+ checker("scripts", master.options),
self.scripts
),
@@ -62,19 +67,19 @@ class Options(urwid.WidgetWrap):
select.Option(
"Default Display Mode",
"M",
- lambda: self.master.options.default_contentview != "auto",
+ checker("default_contentview", master.options),
self.default_displaymode
),
select.Option(
"Palette",
"P",
- lambda: self.master.palette != palettes.DEFAULT,
+ checker("palette", master.options),
self.palette
),
select.Option(
"Show Host",
"w",
- lambda: master.options.showhost,
+ checker("showhost", master.options),
master.options.toggler("showhost")
),
@@ -82,19 +87,19 @@ class Options(urwid.WidgetWrap):
select.Option(
"No Upstream Certs",
"U",
- lambda: master.options.no_upstream_cert,
+ checker("no_upstream_cert", master.options),
master.options.toggler("no_upstream_cert")
),
select.Option(
"TCP Proxying",
"T",
- lambda: master.options.tcp_hosts,
+ checker("tcp_hosts", master.options),
self.tcp_hosts
),
select.Option(
"Don't Verify SSL/TLS Certificates",
"V",
- lambda: master.options.ssl_insecure,
+ checker("ssl_insecure", master.options),
master.options.toggler("ssl_insecure")
),
@@ -102,37 +107,37 @@ class Options(urwid.WidgetWrap):
select.Option(
"Anti-Cache",
"a",
- lambda: master.options.anticache,
+ checker("anticache", master.options),
master.options.toggler("anticache")
),
select.Option(
"Anti-Compression",
"o",
- lambda: master.options.anticomp,
+ checker("anticomp", master.options),
master.options.toggler("anticomp")
),
select.Option(
"Kill Extra",
"x",
- lambda: master.options.replay_kill_extra,
+ checker("replay_kill_extra", master.options),
master.options.toggler("replay_kill_extra")
),
select.Option(
"No Refresh",
"f",
- lambda: not master.options.refresh_server_playback,
+ checker("refresh_server_playback", master.options),
master.options.toggler("refresh_server_playback")
),
select.Option(
"Sticky Auth",
"A",
- lambda: master.options.stickyauth,
+ checker("stickyauth", master.options),
self.sticky_auth
),
select.Option(
"Sticky Cookies",
"t",
- lambda: master.options.stickycookie,
+ checker("stickycookie", master.options),
self.sticky_cookie
),
]
@@ -163,7 +168,7 @@ class Options(urwid.WidgetWrap):
self.master.options.reset()
signals.update_settings.send(self)
signals.status_message.send(
- message = "All select.Options cleared",
+ message = "Options cleared",
expire = 1
)
diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py
index 47e40d98..345512fd 100644
--- a/test/mitmproxy/test_optmanager.py
+++ b/test/mitmproxy/test_optmanager.py
@@ -35,6 +35,7 @@ def test_defaults():
"three": "dthree",
"four": "dfour",
}
+ assert not o.has_changed("one")
newvals = dict(
one="xone",
two="xtwo",
@@ -42,11 +43,13 @@ def test_defaults():
four="xfour",
)
o.update(**newvals)
+ assert o.has_changed("one")
for k, v in newvals.items():
- assert v == o.get(k)
+ assert v == getattr(o, k)
o.reset()
+ assert not o.has_changed("one")
for k, v in o._defaults.items():
- assert v == o.get(k)
+ assert v == getattr(o, k)
def test_options():