mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
Add options.default_contentview
This is the first step in a longer process of revamping content views. For the moment, the option is not exposed on the command line.
This commit is contained in:
parent
944dcbaaa0
commit
b9eb1a3479
@ -24,6 +24,7 @@ class Dumper:
|
|||||||
self.flow_detail = None # type: int
|
self.flow_detail = None # type: int
|
||||||
self.outfp = None # type: typing.io.TextIO
|
self.outfp = None # type: typing.io.TextIO
|
||||||
self.showhost = None # type: bool
|
self.showhost = None # type: bool
|
||||||
|
self.default_contentview = "auto" # type: str
|
||||||
|
|
||||||
def configure(self, options, updated):
|
def configure(self, options, updated):
|
||||||
if options.filtstr:
|
if options.filtstr:
|
||||||
@ -37,6 +38,7 @@ class Dumper:
|
|||||||
self.flow_detail = options.flow_detail
|
self.flow_detail = options.flow_detail
|
||||||
self.outfp = options.tfile
|
self.outfp = options.tfile
|
||||||
self.showhost = options.showhost
|
self.showhost = options.showhost
|
||||||
|
self.default_contentview = options.default_contentview
|
||||||
|
|
||||||
def echo(self, text, ident=None, **style):
|
def echo(self, text, ident=None, **style):
|
||||||
if ident:
|
if ident:
|
||||||
@ -61,7 +63,7 @@ class Dumper:
|
|||||||
self.echo(headers, ident=4)
|
self.echo(headers, ident=4)
|
||||||
if self.flow_detail >= 3:
|
if self.flow_detail >= 3:
|
||||||
_, lines, error = contentviews.get_message_content_view(
|
_, lines, error = contentviews.get_message_content_view(
|
||||||
contentviews.get("Auto"),
|
self.default_contentview,
|
||||||
message
|
message
|
||||||
)
|
)
|
||||||
if error:
|
if error:
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
Mitmproxy Content Views
|
Mitmproxy Content Views
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
mitmproxy includes a set of content views which can be used to format/decode/highlight data.
|
mitmproxy includes a set of content views which can be used to
|
||||||
While they are currently used for HTTP message bodies only, the may be used in other contexts
|
format/decode/highlight data. While they are currently used for HTTP message
|
||||||
in the future, e.g. to decode protobuf messages sent as WebSocket frames.
|
bodies only, the may be used in other contexts in the future, e.g. to decode
|
||||||
|
protobuf messages sent as WebSocket frames.
|
||||||
Thus, the View API is very minimalistic. The only arguments are `data` and `**metadata`,
|
|
||||||
where `data` is the actual content (as bytes). The contents on metadata depend on the protocol in
|
|
||||||
use. For HTTP, the message headers are passed as the ``headers`` keyword argument. For HTTP
|
|
||||||
requests, the query parameters are passed as the ``query`` keyword argument.
|
|
||||||
|
|
||||||
|
Thus, the View API is very minimalistic. The only arguments are `data` and
|
||||||
|
`**metadata`, where `data` is the actual content (as bytes). The contents on
|
||||||
|
metadata depend on the protocol in use. For HTTP, the message headers are
|
||||||
|
passed as the ``headers`` keyword argument. For HTTP requests, the query
|
||||||
|
parameters are passed as the ``query`` keyword argument.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
@ -97,11 +98,7 @@ class View:
|
|||||||
prompt = ()
|
prompt = ()
|
||||||
content_types = []
|
content_types = []
|
||||||
|
|
||||||
def __call__(
|
def __call__(self, data: bytes, **metadata):
|
||||||
self,
|
|
||||||
data: bytes,
|
|
||||||
**metadata
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Transform raw data into human-readable output.
|
Transform raw data into human-readable output.
|
||||||
|
|
||||||
@ -528,7 +525,7 @@ view_prompts = []
|
|||||||
|
|
||||||
def get(name):
|
def get(name):
|
||||||
for i in views:
|
for i in views:
|
||||||
if i.name == name:
|
if i.name.lower() == name.lower():
|
||||||
return i
|
return i
|
||||||
|
|
||||||
|
|
||||||
@ -606,10 +603,13 @@ def safe_to_print(lines, encoding="utf8"):
|
|||||||
yield clean_line
|
yield clean_line
|
||||||
|
|
||||||
|
|
||||||
def get_message_content_view(viewmode, message):
|
def get_message_content_view(viewname, message):
|
||||||
"""
|
"""
|
||||||
Like get_content_view, but also handles message encoding.
|
Like get_content_view, but also handles message encoding.
|
||||||
"""
|
"""
|
||||||
|
viewmode = get(viewname)
|
||||||
|
if not viewmode:
|
||||||
|
get("auto")
|
||||||
try:
|
try:
|
||||||
content = message.content
|
content = message.content
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -47,6 +47,7 @@ class Options(optmanager.OptManager):
|
|||||||
stickyauth: Optional[str] = None,
|
stickyauth: Optional[str] = None,
|
||||||
stream_large_bodies: Optional[int] = None,
|
stream_large_bodies: Optional[int] = None,
|
||||||
verbosity: int = 2,
|
verbosity: int = 2,
|
||||||
|
default_contentview: str = "auto",
|
||||||
outfile: Optional[Tuple[str, str]] = None,
|
outfile: Optional[Tuple[str, str]] = None,
|
||||||
server_replay_ignore_content: bool = False,
|
server_replay_ignore_content: bool = False,
|
||||||
server_replay_ignore_params: Sequence[str] = (),
|
server_replay_ignore_params: Sequence[str] = (),
|
||||||
@ -106,6 +107,7 @@ class Options(optmanager.OptManager):
|
|||||||
self.stickyauth = stickyauth
|
self.stickyauth = stickyauth
|
||||||
self.stream_large_bodies = stream_large_bodies
|
self.stream_large_bodies = stream_large_bodies
|
||||||
self.verbosity = verbosity
|
self.verbosity = verbosity
|
||||||
|
self.default_contentview = default_contentview
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
self.server_replay_ignore_content = server_replay_ignore_content
|
self.server_replay_ignore_content = server_replay_ignore_content
|
||||||
self.server_replay_ignore_params = server_replay_ignore_params
|
self.server_replay_ignore_params = server_replay_ignore_params
|
||||||
|
@ -241,7 +241,7 @@ class FlowView(tabs.Tabs):
|
|||||||
self.flow,
|
self.flow,
|
||||||
(self.tab_offset, "prettyview")
|
(self.tab_offset, "prettyview")
|
||||||
)
|
)
|
||||||
return self.state.default_body_view if override is None else override
|
return self.master.options.default_contentview if override is None else override
|
||||||
|
|
||||||
def conn_text(self, conn):
|
def conn_text(self, conn):
|
||||||
if conn:
|
if conn:
|
||||||
@ -264,7 +264,7 @@ class FlowView(tabs.Tabs):
|
|||||||
" ",
|
" ",
|
||||||
('heading', "["),
|
('heading', "["),
|
||||||
('heading_key', "m"),
|
('heading_key', "m"),
|
||||||
('heading', (":%s]" % viewmode.name)),
|
('heading', (":%s]" % viewmode)),
|
||||||
],
|
],
|
||||||
align="right"
|
align="right"
|
||||||
)
|
)
|
||||||
@ -491,7 +491,7 @@ class FlowView(tabs.Tabs):
|
|||||||
self.state.add_flow_setting(
|
self.state.add_flow_setting(
|
||||||
self.flow,
|
self.flow,
|
||||||
(self.tab_offset, "prettyview"),
|
(self.tab_offset, "prettyview"),
|
||||||
contentviews.get_by_shortcut(t)
|
contentviews.get_by_shortcut(t).name
|
||||||
)
|
)
|
||||||
signals.flow_change.send(self, flow = self.flow)
|
signals.flow_change.send(self, flow = self.flow)
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import urwid
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from mitmproxy import addons
|
from mitmproxy import addons
|
||||||
from mitmproxy import contentviews
|
|
||||||
from mitmproxy import controller
|
from mitmproxy import controller
|
||||||
from mitmproxy import exceptions
|
from mitmproxy import exceptions
|
||||||
from mitmproxy import master
|
from mitmproxy import master
|
||||||
@ -49,7 +48,6 @@ class ConsoleState(state.State):
|
|||||||
state.State.__init__(self)
|
state.State.__init__(self)
|
||||||
self.focus = None
|
self.focus = None
|
||||||
self.follow_focus = None
|
self.follow_focus = None
|
||||||
self.default_body_view = contentviews.get("Auto")
|
|
||||||
self.flowsettings = weakref.WeakKeyDictionary()
|
self.flowsettings = weakref.WeakKeyDictionary()
|
||||||
self.last_search = None
|
self.last_search = None
|
||||||
self.last_filter = ""
|
self.last_filter = ""
|
||||||
@ -612,11 +610,6 @@ class ConsoleMaster(master.Master):
|
|||||||
signals.flowlist_change.send(self)
|
signals.flowlist_change.send(self)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def change_default_display_mode(self, t):
|
|
||||||
v = contentviews.get_by_shortcut(t)
|
|
||||||
self.state.default_body_view = v
|
|
||||||
self.refresh_focus()
|
|
||||||
|
|
||||||
def edit_scripts(self, scripts):
|
def edit_scripts(self, scripts):
|
||||||
self.options.scripts = [x[0] for x in scripts]
|
self.options.scripts = [x[0] for x in scripts]
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class Options(urwid.WidgetWrap):
|
|||||||
select.Option(
|
select.Option(
|
||||||
"Default Display Mode",
|
"Default Display Mode",
|
||||||
"M",
|
"M",
|
||||||
self.has_default_displaymode,
|
lambda: self.master.options.default_contentview != "auto",
|
||||||
self.default_displaymode
|
self.default_displaymode
|
||||||
),
|
),
|
||||||
select.Option(
|
select.Option(
|
||||||
@ -231,11 +231,13 @@ class Options(urwid.WidgetWrap):
|
|||||||
signals.status_prompt_onekey.send(
|
signals.status_prompt_onekey.send(
|
||||||
prompt = "Global default display mode",
|
prompt = "Global default display mode",
|
||||||
keys = contentviews.view_prompts,
|
keys = contentviews.view_prompts,
|
||||||
callback = self.master.change_default_display_mode
|
callback = self.change_default_display_mode
|
||||||
)
|
)
|
||||||
|
|
||||||
def has_default_displaymode(self):
|
def change_default_display_mode(self, t):
|
||||||
return self.master.state.default_body_view.name != "Auto"
|
v = contentviews.get_by_shortcut(t)
|
||||||
|
self.master.options.default_contentview = v.name
|
||||||
|
self.master.refresh_focus()
|
||||||
|
|
||||||
def sticky_auth(self):
|
def sticky_auth(self):
|
||||||
signals.status_prompt.send(
|
signals.status_prompt.send(
|
||||||
|
@ -176,10 +176,10 @@ class StatusBar(urwid.WidgetWrap):
|
|||||||
r.append("[")
|
r.append("[")
|
||||||
r.append(("heading_key", "u"))
|
r.append(("heading_key", "u"))
|
||||||
r.append(":%s]" % self.master.options.stickyauth)
|
r.append(":%s]" % self.master.options.stickyauth)
|
||||||
if self.master.state.default_body_view.name != "Auto":
|
if self.master.options.default_contentview != "auto":
|
||||||
r.append("[")
|
r.append("[")
|
||||||
r.append(("heading_key", "M"))
|
r.append(("heading_key", "M"))
|
||||||
r.append(":%s]" % self.master.state.default_body_view.name)
|
r.append(":%s]" % self.master.options.default_contentview)
|
||||||
|
|
||||||
opts = []
|
opts = []
|
||||||
if self.master.options.anticache:
|
if self.master.options.anticache:
|
||||||
|
@ -233,19 +233,19 @@ def test_get_content_view():
|
|||||||
|
|
||||||
def test_get_message_content_view():
|
def test_get_message_content_view():
|
||||||
r = mitmproxy.test.tutils.treq()
|
r = mitmproxy.test.tutils.treq()
|
||||||
desc, lines, err = cv.get_message_content_view(cv.get("Raw"), r)
|
desc, lines, err = cv.get_message_content_view("raw", r)
|
||||||
assert desc == "Raw"
|
assert desc == "Raw"
|
||||||
|
|
||||||
r.encode("gzip")
|
r.encode("gzip")
|
||||||
desc, lines, err = cv.get_message_content_view(cv.get("Raw"), r)
|
desc, lines, err = cv.get_message_content_view("raw", r)
|
||||||
assert desc == "[decoded gzip] Raw"
|
assert desc == "[decoded gzip] Raw"
|
||||||
|
|
||||||
r.headers["content-encoding"] = "deflate"
|
r.headers["content-encoding"] = "deflate"
|
||||||
desc, lines, err = cv.get_message_content_view(cv.get("Raw"), r)
|
desc, lines, err = cv.get_message_content_view("raw", r)
|
||||||
assert desc == "[cannot decode] Raw"
|
assert desc == "[cannot decode] Raw"
|
||||||
|
|
||||||
r.content = None
|
r.content = None
|
||||||
desc, lines, err = cv.get_message_content_view(cv.get("Raw"), r)
|
desc, lines, err = cv.get_message_content_view("raw", r)
|
||||||
assert list(lines) == [[("error", "content missing")]]
|
assert list(lines) == [[("error", "content missing")]]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user