mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 14:58:38 +00:00
Start rationalizing content views.
We now no longer have distinction between "pretty" view and hex/raw. Instead, we simply a default AUTO view with a global override (M) and a local override (m).
This commit is contained in:
parent
7fef0ecdf5
commit
15cc09f1b8
@ -231,7 +231,7 @@ class ConsoleState(flow.State):
|
||||
def __init__(self):
|
||||
flow.State.__init__(self)
|
||||
self.focus = None
|
||||
self.view_body_mode = contentview.VIEW_CONTENT_PRETTY
|
||||
self.default_body_view = contentview.VIEW_AUTO
|
||||
self.view_flow_mode = common.VIEW_FLOW_REQUEST
|
||||
self.last_script = ""
|
||||
self.last_saveload = ""
|
||||
@ -686,15 +686,6 @@ class ConsoleMaster(flow.FlowMaster):
|
||||
return "Invalid reverse proxy specification"
|
||||
self.server.config.reverse_proxy = s
|
||||
|
||||
def changeview(self, v):
|
||||
if v == "r":
|
||||
self.state.view_body_mode = contentview.VIEW_CONTENT_RAW
|
||||
elif v == "h":
|
||||
self.state.view_body_mode = contentview.VIEW_CONTENT_HEX
|
||||
elif v == "p":
|
||||
self.state.view_body_mode = contentview.VIEW_CONTENT_PRETTY
|
||||
self.refresh_flow(self.currentflow)
|
||||
|
||||
def drawscreen(self):
|
||||
size = self.ui.get_cols_rows()
|
||||
canvas = self.view.render(size, focus=1)
|
||||
|
@ -8,47 +8,53 @@ from ..contrib import jsbeautifier
|
||||
|
||||
VIEW_CUTOFF = 1024*20
|
||||
|
||||
VIEW_CONTENT_RAW = 0
|
||||
VIEW_CONTENT_HEX = 1
|
||||
VIEW_CONTENT_PRETTY = 2
|
||||
VIEW_AUTO = 0
|
||||
VIEW_JSON = 1
|
||||
VIEW_XML = 2
|
||||
VIEW_URLENCODED = 3
|
||||
VIEW_MULTIPART = 4
|
||||
VIEW_JAVASCRIPT = 5
|
||||
VIEW_IMAGE = 6
|
||||
VIEW_RAW = 7
|
||||
VIEW_HEX = 8
|
||||
|
||||
CONTENT_VIEWS = {
|
||||
VIEW_CONTENT_RAW: "raw",
|
||||
VIEW_CONTENT_HEX: "hex",
|
||||
VIEW_CONTENT_PRETTY: "pretty"
|
||||
VIEW_NAMES = {
|
||||
VIEW_AUTO: "Auto",
|
||||
VIEW_JSON: "JSON",
|
||||
VIEW_XML: "XML",
|
||||
VIEW_URLENCODED: "URL-encoded",
|
||||
VIEW_MULTIPART: "Multipart Form",
|
||||
VIEW_JAVASCRIPT: "JavaScript",
|
||||
VIEW_IMAGE: "Image",
|
||||
VIEW_RAW: "Raw",
|
||||
VIEW_HEX: "Hex",
|
||||
}
|
||||
|
||||
VIEW_CONTENT_PRETTY_TYPE_AUTO = 0
|
||||
VIEW_CONTENT_PRETTY_TYPE_JSON = 1
|
||||
VIEW_CONTENT_PRETTY_TYPE_XML = 2
|
||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED = 3
|
||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART = 4
|
||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT = 5
|
||||
VIEW_CONTENT_PRETTY_TYPE_IMAGE = 6
|
||||
|
||||
CONTENT_PRETTY_NAMES = {
|
||||
VIEW_CONTENT_PRETTY_TYPE_JSON: "JSON",
|
||||
VIEW_CONTENT_PRETTY_TYPE_XML: "XML",
|
||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: "URL-encoded",
|
||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: "Multipart Form",
|
||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: "JavaScript",
|
||||
VIEW_CONTENT_PRETTY_TYPE_IMAGE: "Image",
|
||||
VIEW_SHORTCUTS = {
|
||||
"a": VIEW_AUTO,
|
||||
"i": VIEW_IMAGE,
|
||||
"j": VIEW_JAVASCRIPT,
|
||||
"s": VIEW_JSON,
|
||||
"u": VIEW_URLENCODED,
|
||||
"x": VIEW_XML,
|
||||
"r": VIEW_RAW,
|
||||
"h": VIEW_HEX,
|
||||
}
|
||||
|
||||
CONTENT_TYPES_MAP = {
|
||||
"text/html": VIEW_CONTENT_PRETTY_TYPE_XML,
|
||||
"application/json": VIEW_CONTENT_PRETTY_TYPE_JSON,
|
||||
"text/xml": VIEW_CONTENT_PRETTY_TYPE_XML,
|
||||
"multipart/form-data": VIEW_CONTENT_PRETTY_TYPE_MULTIPART,
|
||||
"application/x-www-form-urlencoded": VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
|
||||
"application/x-javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||
"application/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||
"text/javascript": VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||
"image/png": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"image/jpeg": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"image/gif": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"image/vnd.microsoft.icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"image/x-icon": VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"text/html": VIEW_XML,
|
||||
"application/json": VIEW_JSON,
|
||||
"text/xml": VIEW_XML,
|
||||
"multipart/form-data": VIEW_MULTIPART,
|
||||
"application/x-www-form-urlencoded": VIEW_URLENCODED,
|
||||
"application/x-javascript": VIEW_JAVASCRIPT,
|
||||
"application/javascript": VIEW_JAVASCRIPT,
|
||||
"text/javascript": VIEW_JAVASCRIPT,
|
||||
"image/png": VIEW_IMAGE,
|
||||
"image/jpeg": VIEW_IMAGE,
|
||||
"image/gif": VIEW_IMAGE,
|
||||
"image/vnd.microsoft.icon": VIEW_IMAGE,
|
||||
"image/x-icon": VIEW_IMAGE,
|
||||
}
|
||||
|
||||
def trailer(clen, txt):
|
||||
@ -209,36 +215,33 @@ def view_image(hdrs, content):
|
||||
|
||||
|
||||
PRETTY_FUNCTION_MAP = {
|
||||
VIEW_CONTENT_PRETTY_TYPE_XML: view_xmlish,
|
||||
VIEW_CONTENT_PRETTY_TYPE_JSON: view_json,
|
||||
VIEW_CONTENT_PRETTY_TYPE_URLENCODED: view_urlencoded,
|
||||
VIEW_CONTENT_PRETTY_TYPE_MULTIPART: view_multipart,
|
||||
VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT: view_javascript,
|
||||
VIEW_CONTENT_PRETTY_TYPE_IMAGE: view_image,
|
||||
VIEW_XML: view_xmlish,
|
||||
VIEW_JSON: view_json,
|
||||
VIEW_URLENCODED: view_urlencoded,
|
||||
VIEW_MULTIPART: view_multipart,
|
||||
VIEW_JAVASCRIPT: view_javascript,
|
||||
VIEW_IMAGE: view_image,
|
||||
VIEW_HEX: view_hex,
|
||||
VIEW_RAW: view_raw,
|
||||
}
|
||||
|
||||
def get_view_func(viewmode, pretty_type, hdrs, content):
|
||||
def get_view_func(viewmode, hdrs, content):
|
||||
"""
|
||||
Returns a function object.
|
||||
"""
|
||||
if viewmode == VIEW_CONTENT_HEX:
|
||||
return view_hex
|
||||
elif viewmode == VIEW_CONTENT_RAW:
|
||||
return view_raw
|
||||
else:
|
||||
if pretty_type == VIEW_CONTENT_PRETTY_TYPE_AUTO:
|
||||
ctype = hdrs.get("content-type")
|
||||
if ctype:
|
||||
ctype = ctype[0]
|
||||
ct = utils.parse_content_type(ctype) if ctype else None
|
||||
if ct:
|
||||
pretty_type = CONTENT_TYPES_MAP.get("%s/%s"%(ct[0], ct[1]))
|
||||
if not pretty_type and utils.isXML(content):
|
||||
pretty_type = VIEW_CONTENT_PRETTY_TYPE_XML
|
||||
return PRETTY_FUNCTION_MAP.get(pretty_type, view_raw)
|
||||
if viewmode == VIEW_AUTO:
|
||||
ctype = hdrs.get("content-type")
|
||||
if ctype:
|
||||
ctype = ctype[0]
|
||||
ct = utils.parse_content_type(ctype) if ctype else None
|
||||
if ct:
|
||||
viewmode = CONTENT_TYPES_MAP.get("%s/%s"%(ct[0], ct[1]))
|
||||
if not viewmode and utils.isXML(content):
|
||||
viewmode = VIEW_XML
|
||||
return PRETTY_FUNCTION_MAP.get(viewmode, view_raw)
|
||||
|
||||
|
||||
def get_content_view(viewmode, pretty_type, hdrItems, content):
|
||||
def get_content_view(viewmode, hdrItems, content):
|
||||
"""
|
||||
Returns a (msg, body) tuple.
|
||||
"""
|
||||
@ -252,11 +255,7 @@ def get_content_view(viewmode, pretty_type, hdrItems, content):
|
||||
if decoded:
|
||||
content = decoded
|
||||
msg.append("[decoded %s]"%enc[0])
|
||||
|
||||
if viewmode == VIEW_CONTENT_PRETTY and pretty_type != VIEW_CONTENT_PRETTY_TYPE_AUTO:
|
||||
msg.append("[forced to %s]"%(CONTENT_PRETTY_NAMES[pretty_type]))
|
||||
func = get_view_func(viewmode, pretty_type, hdrs, content)
|
||||
|
||||
func = get_view_func(viewmode, hdrs, content)
|
||||
ret = func(hdrs, content)
|
||||
if not ret:
|
||||
ret = view_raw(hdrs, content)
|
||||
|
@ -27,26 +27,15 @@ def _mkhelp():
|
||||
("d", "delete flow"),
|
||||
("D", "duplicate flow"),
|
||||
("e", "edit request/response"),
|
||||
("m", "change body display mode"),
|
||||
(None,
|
||||
common.highlight_key("raw", "r") +
|
||||
[("text", ": raw data")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("pretty", "p") +
|
||||
[("text", ": pretty-print XML, HTML and JSON")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("hex", "h") +
|
||||
[("text", ": hex dump")]
|
||||
),
|
||||
("p", "previous flow"),
|
||||
("r", "replay request"),
|
||||
("T", "override content-type for pretty-printed body"),
|
||||
("m", "change body display mode for this entity"),
|
||||
(None,
|
||||
common.highlight_key("automatic", "a") +
|
||||
[("text", ": automatic detection")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("hex", "h") +
|
||||
[("text", ": Hex")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("image", "i") +
|
||||
[("text", ": Image")]
|
||||
@ -63,10 +52,17 @@ def _mkhelp():
|
||||
common.highlight_key("urlencoded", "u") +
|
||||
[("text", ": URL-encoded data")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("raw", "r") +
|
||||
[("text", ": raw data")]
|
||||
),
|
||||
(None,
|
||||
common.highlight_key("xml", "x") +
|
||||
[("text", ": XML")]
|
||||
),
|
||||
("M", "change default body display mode"),
|
||||
("p", "previous flow"),
|
||||
("r", "replay request"),
|
||||
("V", "revert changes to request"),
|
||||
("v", "view body in external viewer"),
|
||||
("w", "save all flows matching current limit"),
|
||||
@ -128,14 +124,14 @@ class FlowView(common.WWrap):
|
||||
else:
|
||||
self.view_request()
|
||||
|
||||
def _cached_conn_text(self, content, hdrItems, viewmode, pretty_type):
|
||||
def _cached_conn_text(self, content, hdrItems, viewmode):
|
||||
txt = common.format_keyvals(
|
||||
[(h+":", v) for (h, v) in hdrItems],
|
||||
key = "header",
|
||||
val = "text"
|
||||
)
|
||||
if content:
|
||||
msg, body = contentview.get_content_view(viewmode, pretty_type, hdrItems, content)
|
||||
msg, body = contentview.get_content_view(viewmode, hdrItems, content)
|
||||
title = urwid.AttrWrap(urwid.Columns([
|
||||
urwid.Text(
|
||||
[
|
||||
@ -147,7 +143,7 @@ class FlowView(common.WWrap):
|
||||
" ",
|
||||
('heading', "["),
|
||||
('heading_key', "m"),
|
||||
('heading', (":%s]"%contentview.CONTENT_VIEWS[self.master.state.view_body_mode])),
|
||||
('heading', (":%s]"%contentview.VIEW_NAMES[viewmode])),
|
||||
],
|
||||
align="right"
|
||||
),
|
||||
@ -190,24 +186,22 @@ class FlowView(common.WWrap):
|
||||
)
|
||||
return f
|
||||
|
||||
def _conn_text(self, conn, viewmode, pretty_type):
|
||||
def _conn_text(self, conn, viewmode):
|
||||
return cache.callback(
|
||||
self, "_cached_conn_text",
|
||||
conn.content,
|
||||
tuple(tuple(i) for i in conn.headers.lst),
|
||||
viewmode,
|
||||
pretty_type
|
||||
viewmode
|
||||
)
|
||||
|
||||
def view_request(self):
|
||||
self.state.view_flow_mode = common.VIEW_FLOW_REQUEST
|
||||
body = self._conn_text(
|
||||
self.flow.request,
|
||||
self.state.view_body_mode,
|
||||
self.state.get_flow_setting(
|
||||
self.flow,
|
||||
(common.VIEW_FLOW_REQUEST, "prettyview"),
|
||||
contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO
|
||||
self.state.default_body_view
|
||||
)
|
||||
)
|
||||
self.w = self.wrap_body(common.VIEW_FLOW_REQUEST, body)
|
||||
@ -218,11 +212,10 @@ class FlowView(common.WWrap):
|
||||
if self.flow.response:
|
||||
body = self._conn_text(
|
||||
self.flow.response,
|
||||
self.state.view_body_mode,
|
||||
self.state.get_flow_setting(
|
||||
self.flow,
|
||||
(common.VIEW_FLOW_RESPONSE, "prettyview"),
|
||||
contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO
|
||||
self.state.default_body_view
|
||||
)
|
||||
)
|
||||
else:
|
||||
@ -377,22 +370,19 @@ class FlowView(common.WWrap):
|
||||
def view_prev_flow(self, flow):
|
||||
return self._view_nextprev_flow("prev", flow)
|
||||
|
||||
def change_pretty_type(self, t):
|
||||
d = {
|
||||
"a": contentview.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
"i": contentview.VIEW_CONTENT_PRETTY_TYPE_IMAGE,
|
||||
"j": contentview.VIEW_CONTENT_PRETTY_TYPE_JAVASCRIPT,
|
||||
"s": contentview.VIEW_CONTENT_PRETTY_TYPE_JSON,
|
||||
"u": contentview.VIEW_CONTENT_PRETTY_TYPE_URLENCODED,
|
||||
"x": contentview.VIEW_CONTENT_PRETTY_TYPE_XML,
|
||||
}
|
||||
def change_this_display_mode(self, t):
|
||||
self.state.add_flow_setting(
|
||||
self.flow,
|
||||
(self.state.view_flow_mode, "prettyview"),
|
||||
d.get(t)
|
||||
contentview.VIEW_SHORTCUTS.get(t)
|
||||
)
|
||||
self.master.refresh_flow(self.flow)
|
||||
|
||||
def change_default_display_mode(self, t):
|
||||
v = contentview.VIEW_SHORTCUTS.get(t)
|
||||
self.state.default_body_view = v
|
||||
self.master.refresh_flow(self.flow)
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key == " ":
|
||||
self.view_next_flow(self.flow)
|
||||
@ -464,13 +454,34 @@ class FlowView(common.WWrap):
|
||||
key = None
|
||||
elif key == "m":
|
||||
self.master.prompt_onekey(
|
||||
"View",
|
||||
"Display mode",
|
||||
(
|
||||
("raw", "r"),
|
||||
("pretty", "p"),
|
||||
("auto detect", "a"),
|
||||
("hex", "h"),
|
||||
("image", "i"),
|
||||
("javascript", "j"),
|
||||
("json", "s"),
|
||||
("raw", "r"),
|
||||
("urlencoded", "u"),
|
||||
("xmlish", "x"),
|
||||
),
|
||||
self.master.changeview
|
||||
self.change_this_display_mode
|
||||
)
|
||||
key = None
|
||||
elif key == "M":
|
||||
self.master.prompt_onekey(
|
||||
"Global default display mode",
|
||||
(
|
||||
("auto detect", "a"),
|
||||
("hex", "h"),
|
||||
("image", "i"),
|
||||
("javascript", "j"),
|
||||
("json", "s"),
|
||||
("raw", "r"),
|
||||
("urlencoded", "u"),
|
||||
("xmlish", "x"),
|
||||
),
|
||||
self.change_default_display_mode
|
||||
)
|
||||
key = None
|
||||
elif key == "p":
|
||||
@ -480,20 +491,6 @@ class FlowView(common.WWrap):
|
||||
if r:
|
||||
self.master.statusbar.message(r)
|
||||
self.master.refresh_flow(self.flow)
|
||||
elif key == "T":
|
||||
self.master.prompt_onekey(
|
||||
"Pretty-Print format",
|
||||
(
|
||||
("auto detect", "a"),
|
||||
("image", "i"),
|
||||
("javascript", "j"),
|
||||
("json", "s"),
|
||||
("urlencoded", "u"),
|
||||
("xmlish", "x"),
|
||||
),
|
||||
self.change_pretty_type
|
||||
)
|
||||
key = None
|
||||
elif key == "V":
|
||||
self.state.revert(self.flow)
|
||||
self.master.refresh_flow(self.flow)
|
||||
|
@ -12,24 +12,21 @@ class uContentView(libpry.AutoTree):
|
||||
|
||||
def test_get_view_func(self):
|
||||
f = cv.get_view_func(
|
||||
cv.VIEW_CONTENT_HEX,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_HEX,
|
||||
flow.ODictCaseless(),
|
||||
"foo"
|
||||
)
|
||||
assert f is cv.view_hex
|
||||
|
||||
f = cv.get_view_func(
|
||||
cv.VIEW_CONTENT_RAW,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
flow.ODictCaseless(),
|
||||
"foo"
|
||||
)
|
||||
assert f is cv.view_raw
|
||||
|
||||
f = cv.get_view_func(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
flow.ODictCaseless(
|
||||
[["content-type", "text/html"]],
|
||||
),
|
||||
@ -38,8 +35,7 @@ class uContentView(libpry.AutoTree):
|
||||
assert f is cv.view_xmlish
|
||||
|
||||
f = cv.get_view_func(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
flow.ODictCaseless(
|
||||
[["content-type", "text/flibble"]],
|
||||
),
|
||||
@ -48,8 +44,7 @@ class uContentView(libpry.AutoTree):
|
||||
assert f is cv.view_raw
|
||||
|
||||
f = cv.get_view_func(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
flow.ODictCaseless(
|
||||
[["content-type", "text/flibble"]],
|
||||
),
|
||||
@ -118,33 +113,28 @@ Larry
|
||||
|
||||
def test_get_content_view(self):
|
||||
r = cv.get_content_view(
|
||||
cv.VIEW_CONTENT_RAW,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_RAW,
|
||||
[["content-type", "application/json"]],
|
||||
"[1, 2, 3]"
|
||||
)
|
||||
assert r[0] == "Raw"
|
||||
assert "Raw" in r[0]
|
||||
|
||||
r = cv.get_content_view(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
[["content-type", "application/json"]],
|
||||
"[1, 2, 3]"
|
||||
)
|
||||
assert r[0] == "JSON"
|
||||
|
||||
|
||||
r = cv.get_content_view(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
[["content-type", "application/json"]],
|
||||
"[1, 2"
|
||||
)
|
||||
assert r[0] == "Raw"
|
||||
|
||||
r = cv.get_content_view(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_AUTO,
|
||||
cv.VIEW_AUTO,
|
||||
[
|
||||
["content-type", "application/json"],
|
||||
["content-encoding", "gzip"]
|
||||
@ -154,10 +144,8 @@ Larry
|
||||
assert "decoded gzip" in r[0]
|
||||
assert "JSON" in r[0]
|
||||
|
||||
|
||||
r = cv.get_content_view(
|
||||
cv.VIEW_CONTENT_PRETTY,
|
||||
cv.VIEW_CONTENT_PRETTY_TYPE_XML,
|
||||
cv.VIEW_XML,
|
||||
[
|
||||
["content-type", "application/json"],
|
||||
["content-encoding", "gzip"]
|
||||
|
Loading…
Reference in New Issue
Block a user