aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy
diff options
context:
space:
mode:
authorClemens <cle1000.cb@gmail.com>2016-08-03 12:17:19 +0200
committerClemens <cle1000.cb@gmail.com>2016-08-03 12:17:19 +0200
commite036bc9304c76b63169da11c6721745484d6da10 (patch)
treeb0c882fb3a18aa7d63b1e5d05486fd734057c35b /mitmproxy
parent34fe391afbe18f89d774137f82620024f697ab6a (diff)
downloadmitmproxy-e036bc9304c76b63169da11c6721745484d6da10.tar.gz
mitmproxy-e036bc9304c76b63169da11c6721745484d6da10.tar.bz2
mitmproxy-e036bc9304c76b63169da11c6721745484d6da10.zip
integrate simplified contentviews
Diffstat (limited to 'mitmproxy')
-rw-r--r--mitmproxy/builtins/dumper.py26
-rw-r--r--mitmproxy/console/flowview.py13
-rw-r--r--mitmproxy/contentviews.py116
3 files changed, 71 insertions, 84 deletions
diff --git a/mitmproxy/builtins/dumper.py b/mitmproxy/builtins/dumper.py
index b1367e12..a98c9b46 100644
--- a/mitmproxy/builtins/dumper.py
+++ b/mitmproxy/builtins/dumper.py
@@ -63,20 +63,12 @@ class Dumper(object):
)
self.echo(headers, ident=4)
if self.flow_detail >= 3:
- try:
- content = message.content
- except ValueError:
- content = message.get_content(strict=False)
-
- if content is None:
- self.echo("(content missing)", ident=4)
- elif content:
- self.echo("")
-
- _, lines = contentviews.get_content_view_with_message_encoding(
- message,
- contentviews.get("Auto")
+ _, lines, error = contentviews.get_message_content_view(
+ contentviews.get("Auto"),
+ message
)
+ if error:
+ ctx.log.debug(error)
styles = dict(
highlight=dict(bold=True),
@@ -95,13 +87,13 @@ class Dumper(object):
else:
lines_to_echo = lines
- lines_to_echo = list(lines_to_echo)
-
content = u"\r\n".join(
u"".join(colorful(line)) for line in lines_to_echo
)
+ if content:
+ self.echo("")
+ self.echo(content)
- self.echo(content)
if next(lines, None):
self.echo("(cut off)", ident=4, dim=True)
@@ -251,4 +243,4 @@ class Dumper(object):
server=repr(f.server_conn.address),
direction=direction,
))
- self._echo_message(message)
+ self._echo_message(message) \ No newline at end of file
diff --git a/mitmproxy/console/flowview.py b/mitmproxy/console/flowview.py
index c1001a5a..323aefd2 100644
--- a/mitmproxy/console/flowview.py
+++ b/mitmproxy/console/flowview.py
@@ -80,7 +80,7 @@ def _mkhelp():
("r", "replay request"),
("V", "revert changes to request"),
("v", "view body in external viewer"),
- ("w", "save all flows matching current limit"),
+ ("w", "save all flows matching current view filter"),
("W", "save this flow"),
("x", "delete body"),
("z", "encode/decode a request/response"),
@@ -206,10 +206,11 @@ class FlowView(tabs.Tabs):
)
def _get_content_view(self, message, viewmode, max_lines, _):
-
- description, lines = contentviews.get_content_view_with_message_encoding(
- message, viewmode
+ description, lines, error = contentviews.get_message_content_view(
+ viewmode, message
)
+ if error:
+ signals.add_log(error, "error")
# Give hint that you have to tab for the response.
if description == "No content" and isinstance(message, models.HTTPRequest):
description = "No request content (press tab to view response)"
@@ -687,6 +688,7 @@ class FlowView(tabs.Tabs):
keys = (
("gzip", "z"),
("deflate", "d"),
+ ("brotli", "b"),
),
callback = self.encode_callback,
args = (conn,)
@@ -700,6 +702,7 @@ class FlowView(tabs.Tabs):
encoding_map = {
"z": "gzip",
"d": "deflate",
+ "b": "brotli",
}
conn.encode(encoding_map[key])
- signals.flow_change.send(self, flow = self.flow)
+ signals.flow_change.send(self, flow = self.flow) \ No newline at end of file
diff --git a/mitmproxy/contentviews.py b/mitmproxy/contentviews.py
index 88d979e4..807638dc 100644
--- a/mitmproxy/contentviews.py
+++ b/mitmproxy/contentviews.py
@@ -14,31 +14,27 @@ requests, the query parameters are passed as the ``query`` keyword argument.
"""
from __future__ import absolute_import, print_function, division
+import cssutils
import datetime
+import html2text
+import jsbeautifier
import json
import logging
-import subprocess
-import sys
-import math
-
-from typing import Mapping # noqa
-
-import html2text
import lxml.etree
import lxml.html
import six
+import subprocess
+import traceback
from PIL import ExifTags
from PIL import Image
-from six import BytesIO
-
-from mitmproxy import models
from mitmproxy import exceptions
-from mitmproxy.contrib import jsbeautifier
from mitmproxy.contrib.wbxml import ASCommandResponse
from netlib import http
from netlib import multidict
-from netlib.http import url
from netlib import strutils
+from netlib.http import url
+from six import BytesIO
+from typing import Mapping # noqa
try:
import pyamf
@@ -46,17 +42,6 @@ try:
except ImportError: # pragma no cover
pyamf = None
-try:
- import cssutils
-except ImportError: # pragma no cover
- cssutils = None
-else:
- cssutils.log.setLevel(logging.CRITICAL)
-
- cssutils.ser.prefs.keepComments = True
- cssutils.ser.prefs.omitLastSemicolon = False
- cssutils.ser.prefs.indentClosingBrace = False
- cssutils.ser.prefs.validOnly = False
# Default view cutoff *in lines*
VIEW_CUTOFF = 512
@@ -273,7 +258,7 @@ class ViewHTMLOutline(View):
content_types = ["text/html"]
def __call__(self, data, **metadata):
- data = data.decode("utf-8")
+ data = data.decode("utf-8", "replace")
h = html2text.HTML2Text(baseurl="")
h.ignore_images = True
h.body_width = 0
@@ -400,6 +385,7 @@ class ViewJavaScript(View):
def __call__(self, data, **metadata):
opts = jsbeautifier.default_options()
opts.indent_size = 2
+ data = data.decode("utf-8", "replace")
res = jsbeautifier.beautify(data, opts)
return "JavaScript", format_text(res)
@@ -412,11 +398,14 @@ class ViewCSS(View):
]
def __call__(self, data, **metadata):
- if cssutils:
- sheet = cssutils.parseString(data)
- beautified = sheet.cssText
- else:
- beautified = data
+ cssutils.log.setLevel(logging.CRITICAL)
+ cssutils.ser.prefs.keepComments = True
+ cssutils.ser.prefs.omitLastSemicolon = False
+ cssutils.ser.prefs.indentClosingBrace = False
+ cssutils.ser.prefs.validOnly = False
+
+ sheet = cssutils.parseString(data)
+ beautified = sheet.cssText
return "CSS", format_text(beautified)
@@ -619,35 +608,38 @@ def safe_to_print(lines, encoding="utf8"):
yield clean_line
-def get_content_view_with_message_encoding(message, viewmode):
+def get_message_content_view(viewmode, message):
+ """
+ Like get_content_view, but also handles message encoding.
+ """
try:
content = message.content
- if content != message.raw_content:
+ except ValueError:
+ content = message.raw_content
+ enc = "[cannot decode]"
+ else:
+ if isinstance(message, http.Message) and content != message.raw_content:
enc = "[decoded {}]".format(
message.headers.get("content-encoding")
)
else:
enc = None
- except ValueError:
- content = message.raw_content
- enc = "[cannot decode]"
- try:
- query = None
- if isinstance(message, models.HTTPRequest):
- query = message.query
- description, lines = get_content_view(
- viewmode, content, headers=message.headers, query=query
- )
- except exceptions.ContentViewException:
- description, lines = get_content_view(
- get("Raw"), content, headers=message.headers
- )
- description = description.replace("Raw", "Couldn't parse: falling back to Raw")
+
+ if content is None:
+ return "", iter([[("error", "content missing")]]), None
+
+ query = message.query if isinstance(message, http.Request) else None
+ headers = message.headers if isinstance(message, http.Message) else None
+
+ description, lines, error = get_content_view(
+ viewmode, content, headers=headers, query=query
+ )
if enc:
- description = " ".join([enc, description])
+ description = "{} {}".format(enc, description)
+
+ return description, lines, error
- return description, lines
def get_content_view(viewmode, data, **metadata):
"""
@@ -656,24 +648,24 @@ def get_content_view(viewmode, data, **metadata):
data, **metadata: arguments passed to View instance.
Returns:
- A (description, content generator) tuple.
+ A (description, content generator, error) tuple.
+ If the content view raised an exception generating the view,
+ the exception is returned in error and the flow is formatted in raw mode.
In contrast to calling the views directly, text is always safe-to-print unicode.
-
- Raises:
- ContentViewException, if the content view threw an error.
"""
try:
ret = viewmode(data, **metadata)
+ if ret is None:
+ ret = "Couldn't parse: falling back to Raw", get("Raw")(data, **metadata)[1]
+ desc, content = ret
+ error = None
# Third-party viewers can fail in unexpected ways...
- except Exception as e:
- six.reraise(
- exceptions.ContentViewException,
- exceptions.ContentViewException(str(e)),
- sys.exc_info()[2]
- )
- if not ret:
+ except Exception:
desc = "Couldn't parse: falling back to Raw"
_, content = get("Raw")(data, **metadata)
- else:
- desc, content = ret
- return desc, safe_to_print(content)
+ error = "{} Content viewer failed: \n{}".format(
+ getattr(viewmode, "name"),
+ traceback.format_exc()
+ )
+
+ return desc, safe_to_print(content), error \ No newline at end of file