diff options
author | Aldo Cortesi <aldo@corte.si> | 2016-06-01 16:26:55 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@corte.si> | 2016-06-01 16:26:55 +1200 |
commit | 92b24c66530fa9aba804a72e46dd8f34d0f23206 (patch) | |
tree | 50b7f496602784e7d3e146ea51f6037697f07dc2 | |
parent | 1dd078beb23aa0b483f945eed39c0136984f81a6 (diff) | |
parent | 137ee28bd6f9676ab1efc44354eda24077540023 (diff) | |
download | mitmproxy-92b24c66530fa9aba804a72e46dd8f34d0f23206.tar.gz mitmproxy-92b24c66530fa9aba804a72e46dd8f34d0f23206.tar.bz2 mitmproxy-92b24c66530fa9aba804a72e46dd8f34d0f23206.zip |
Merge pull request #1183 from mitmproxy/module-imports
use module-level imports only
66 files changed, 618 insertions, 504 deletions
diff --git a/mitmproxy/cmdline.py b/mitmproxy/cmdline.py index 5ea76e44..a873143d 100644 --- a/mitmproxy/cmdline.py +++ b/mitmproxy/cmdline.py @@ -1,15 +1,17 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division + +import base64 import os import re -import base64 import configargparse -from netlib.tcp import Address, sslversion_choices -import netlib.http.url +from mitmproxy import filt +from mitmproxy import version +from mitmproxy.proxy import config from netlib import human -from . import filt, version -from .proxy import config +from netlib import tcp +from netlib.http import url APP_HOST = "mitm.it" APP_PORT = 80 @@ -104,17 +106,17 @@ def parse_setheader(s): return _parse_hook(s) -def parse_server_spec(url): +def parse_server_spec(spec): try: - p = netlib.http.url.parse(url) + p = url.parse(spec) if p[0] not in ("http", "https"): raise ValueError() except ValueError: raise configargparse.ArgumentTypeError( - "Invalid server specification: %s" % url + "Invalid server specification: %s" % spec ) - address = Address(p[1:3]) + address = tcp.Address(p[1:3]) scheme = p[0].lower() return config.ServerSpec(scheme, address) @@ -477,14 +479,14 @@ def proxy_ssl_options(parser): group.add_argument( "--ssl-version-client", dest="ssl_version_client", default="secure", action="store", - choices=sslversion_choices.keys(), + choices=tcp.sslversion_choices.keys(), help="Set supported SSL/TLS versions for client connections. " "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." ) group.add_argument( "--ssl-version-server", dest="ssl_version_server", default="secure", action="store", - choices=sslversion_choices.keys(), + choices=tcp.sslversion_choices.keys(), help="Set supported SSL/TLS versions for server connections. " "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." ) diff --git a/mitmproxy/console/__init__.py b/mitmproxy/console/__init__.py index 1a70157a..00fb4b1b 100644 --- a/mitmproxy/console/__init__.py +++ b/mitmproxy/console/__init__.py @@ -1,8 +1,7 @@ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, division import mailcap import mimetypes -import tempfile import os import os.path import shlex @@ -10,16 +9,28 @@ import signal import stat import subprocess import sys +import tempfile import traceback -import urwid import weakref -from netlib import tcp +import urwid -from .. import flow, script, contentviews, controller -from . import flowlist, flowview, help, window, signals, options -from . import grideditor, palettes, statusbar, palettepicker -from ..exceptions import FlowReadException, ScriptException +from mitmproxy import contentviews +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import flow +from mitmproxy import script +from mitmproxy.console import flowlist +from mitmproxy.console import flowview +from mitmproxy.console import grideditor +from mitmproxy.console import help +from mitmproxy.console import options +from mitmproxy.console import palettepicker +from mitmproxy.console import palettes +from mitmproxy.console import signals +from mitmproxy.console import statusbar +from mitmproxy.console import window +from netlib import tcp EVENTLOG_SIZE = 500 @@ -231,7 +242,7 @@ class ConsoleMaster(flow.FlowMaster): for i in options.scripts: try: self.load_script(i) - except ScriptException as e: + except exceptions.ScriptException as e: print("Script load error: {}".format(e), file=sys.stderr) sys.exit(1) @@ -352,7 +363,7 @@ class ConsoleMaster(flow.FlowMaster): """ try: return flow.read_flows_from_paths(path) - except FlowReadException as e: + except exceptions.FlowReadException as e: signals.status_message.send(message=e.strerror) def client_playback_path(self, path): @@ -636,7 +647,7 @@ class ConsoleMaster(flow.FlowMaster): reterr = None try: flow.FlowMaster.load_flows_file(self, path) - except FlowReadException as e: + except exceptions.FlowReadException as e: reterr = str(e) signals.flowlist_change.send(self) return reterr @@ -666,7 +677,7 @@ class ConsoleMaster(flow.FlowMaster): for command in commands: try: self.load_script(command) - except ScriptException as e: + except exceptions.ScriptException as e: signals.status_message.send( message='Error loading "{}".'.format(command) ) diff --git a/mitmproxy/console/common.py b/mitmproxy/console/common.py index a3ed5dc8..acb7fc35 100644 --- a/mitmproxy/console/common.py +++ b/mitmproxy/console/common.py @@ -1,18 +1,17 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division + +import os import urwid import urwid.util -import os import netlib +from mitmproxy import flow +from mitmproxy import models +from mitmproxy import utils +from mitmproxy.console import signals from netlib import human -from .. import utils -from .. import flow -from ..models import decoded -from . import signals - - try: import pyperclip except: @@ -260,7 +259,7 @@ def copy_flow_format_data(part, scope, flow): if scope in ("q", "a"): if flow.request.content is None: return None, "Request content is missing" - with decoded(flow.request): + with models.decoded(flow.request): if part == "h": data += netlib.http.http1.assemble_request(flow.request) elif part == "c": @@ -273,7 +272,7 @@ def copy_flow_format_data(part, scope, flow): if scope in ("s", "a") and flow.response: if flow.response.content is None: return None, "Response content is missing" - with decoded(flow.response): + with models.decoded(flow.response): if part == "h": data += netlib.http.http1.assemble_response(flow.response) elif part == "c": diff --git a/mitmproxy/console/flowdetailview.py b/mitmproxy/console/flowdetailview.py index ca083b10..e2c28e71 100644 --- a/mitmproxy/console/flowdetailview.py +++ b/mitmproxy/console/flowdetailview.py @@ -1,7 +1,9 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division + import urwid -from . import common, searchable -from .. import utils + +from mitmproxy import utils +from mitmproxy.console import common, searchable def maybe_timestamp(base, attr): diff --git a/mitmproxy/console/flowlist.py b/mitmproxy/console/flowlist.py index 1e65e3eb..eb1e76fb 100644 --- a/mitmproxy/console/flowlist.py +++ b/mitmproxy/console/flowlist.py @@ -1,9 +1,10 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division + import urwid import netlib.http.url - -from . import common, signals +from mitmproxy.console import common +from mitmproxy.console import signals def _mkhelp(): diff --git a/mitmproxy/console/flowview.py b/mitmproxy/console/flowview.py index 2010cecd..e9b23176 100644 --- a/mitmproxy/console/flowview.py +++ b/mitmproxy/console/flowview.py @@ -1,17 +1,25 @@ -from __future__ import absolute_import, division +from __future__ import absolute_import, print_function, division + +import math import os -import traceback import sys +import traceback -import math import urwid -from netlib.http import Headers, status_codes -from . import common, grideditor, signals, searchable, tabs -from . import flowdetailview -from .. import utils, controller, contentviews -from ..models import HTTPRequest, HTTPResponse, decoded -from ..exceptions import ContentViewException +from mitmproxy import contentviews +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import models +from mitmproxy import utils +from mitmproxy.console import common +from mitmproxy.console import flowdetailview +from mitmproxy.console import grideditor +from mitmproxy.console import searchable +from mitmproxy.console import signals +from mitmproxy.console import tabs +from netlib.http import Headers +from netlib.http import status_codes class SearchError(Exception): @@ -193,12 +201,12 @@ class FlowView(tabs.Tabs): try: query = None - if isinstance(message, HTTPRequest): + if isinstance(message, models.HTTPRequest): query = message.query description, lines = contentviews.get_content_view( viewmode, message.content, headers=message.headers, query=query ) - except ContentViewException: + except exceptions.ContentViewException: s = "Content viewer failed: \n" + traceback.format_exc() signals.add_event(s, "error") description, lines = contentviews.get_content_view( @@ -207,7 +215,7 @@ class FlowView(tabs.Tabs): description = description.replace("Raw", "Couldn't parse: falling back to Raw") # Give hint that you have to tab for the response. - if description == "No content" and isinstance(message, HTTPRequest): + if description == "No content" and isinstance(message, models.HTTPRequest): description = "No request content (press tab to view response)" # If the users has a wide terminal, he gets fewer lines; this should not be an issue. @@ -372,7 +380,7 @@ class FlowView(tabs.Tabs): message = self.flow.request else: if not self.flow.response: - self.flow.response = HTTPResponse( + self.flow.response = models.HTTPResponse( self.flow.request.http_version, 200, "OK", Headers(), "" ) @@ -399,7 +407,7 @@ class FlowView(tabs.Tabs): ) ) if part == "r": - with decoded(message): + with models.decoded(message): # Fix an issue caused by some editors when editing a # request/response body. Many editors make it hard to save a # file without a terminating newline on the last line. When diff --git a/mitmproxy/console/grideditor.py b/mitmproxy/console/grideditor.py index ea26d966..9fa51ccb 100644 --- a/mitmproxy/console/grideditor.py +++ b/mitmproxy/console/grideditor.py @@ -1,15 +1,18 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division import copy -import re import os -import urwid - -from netlib.http import user_agents, cookies +import re -from . import common, signals -from .. import utils, filt, script +import urwid +from mitmproxy import filt +from mitmproxy import script +from mitmproxy import utils +from mitmproxy.console import common +from mitmproxy.console import signals +from netlib.http import cookies +from netlib.http import user_agents FOOTER = [ ('heading_key', "enter"), ":edit ", diff --git a/mitmproxy/console/help.py b/mitmproxy/console/help.py index 0c264ebf..26cb4ed3 100644 --- a/mitmproxy/console/help.py +++ b/mitmproxy/console/help.py @@ -1,9 +1,11 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division import urwid -from . import common, signals -from .. import filt, version +from mitmproxy import filt +from mitmproxy import version +from mitmproxy.console import common +from mitmproxy.console import signals footer = [ ("heading", 'mitmproxy v%s ' % version.VERSION), diff --git a/mitmproxy/console/options.py b/mitmproxy/console/options.py index 5c9e0cc9..5a01c9d5 100644 --- a/mitmproxy/console/options.py +++ b/mitmproxy/console/options.py @@ -1,8 +1,13 @@ +from __future__ import absolute_import, print_function, division + import urwid -from .. import contentviews -from . import common, signals, grideditor -from . import select, palettes +from mitmproxy import contentviews +from mitmproxy.console import common +from mitmproxy.console import grideditor +from mitmproxy.console import palettes +from mitmproxy.console import select +from mitmproxy.console import signals footer = [ ('heading_key', "enter/space"), ":toggle ", diff --git a/mitmproxy/console/palettepicker.py b/mitmproxy/console/palettepicker.py index 51ad0606..f2acba0a 100644 --- a/mitmproxy/console/palettepicker.py +++ b/mitmproxy/console/palettepicker.py @@ -1,6 +1,11 @@ +from __future__ import absolute_import, print_function, division + import urwid -from . import select, common, palettes, signals +from mitmproxy.console import common +from mitmproxy.console import palettes +from mitmproxy.console import select +from mitmproxy.console import signals footer = [ ('heading_key', "enter/space"), ":select", diff --git a/mitmproxy/console/palettes.py b/mitmproxy/console/palettes.py index bd370181..36cc3ac0 100644 --- a/mitmproxy/console/palettes.py +++ b/mitmproxy/console/palettes.py @@ -3,6 +3,7 @@ # # http://urwid.org/manual/displayattributes.html # +from __future__ import absolute_import, print_function, division class Palette: diff --git a/mitmproxy/console/pathedit.py b/mitmproxy/console/pathedit.py index 4447070b..0eae9123 100644 --- a/mitmproxy/console/pathedit.py +++ b/mitmproxy/console/pathedit.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, print_function, division + import glob import os.path diff --git a/mitmproxy/console/searchable.py b/mitmproxy/console/searchable.py index cff1f0a1..c60d1cd9 100644 --- a/mitmproxy/console/searchable.py +++ b/mitmproxy/console/searchable.py @@ -1,6 +1,8 @@ +from __future__ import absolute_import, print_function, division + import urwid -from . import signals +from mitmproxy.console import signals class Highlight(urwid.AttrMap): diff --git a/mitmproxy/console/select.py b/mitmproxy/console/select.py index 7c6d1e96..091f07a2 100644 --- a/mitmproxy/console/select.py +++ b/mitmproxy/console/select.py @@ -1,6 +1,8 @@ +from __future__ import absolute_import, print_function, division + import urwid -from . import common +from mitmproxy.console import common class _OptionWidget(urwid.WidgetWrap): diff --git a/mitmproxy/console/signals.py b/mitmproxy/console/signals.py index 6a439bf3..b57ebf0c 100644 --- a/mitmproxy/console/signals.py +++ b/mitmproxy/console/signals.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, print_function, division + import blinker # Show a status message in the action bar diff --git a/mitmproxy/console/statusbar.py b/mitmproxy/console/statusbar.py index d57ac69c..b3e1517f 100644 --- a/mitmproxy/console/statusbar.py +++ b/mitmproxy/console/statusbar.py @@ -1,10 +1,14 @@ +from __future__ import absolute_import, print_function, division + import os.path import urwid import netlib.utils +from mitmproxy.console import common +from mitmproxy.console import pathedit +from mitmproxy.console import signals from netlib import human -from . import pathedit, signals, common class ActionBar(urwid.WidgetWrap): diff --git a/mitmproxy/console/tabs.py b/mitmproxy/console/tabs.py index b5423038..bfcdeba3 100644 --- a/mitmproxy/console/tabs.py +++ b/mitmproxy/console/tabs.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, print_function, division + import urwid diff --git a/mitmproxy/console/window.py b/mitmproxy/console/window.py index 47c284e4..25780daf 100644 --- a/mitmproxy/console/window.py +++ b/mitmproxy/console/window.py @@ -1,5 +1,8 @@ +from __future__ import absolute_import, print_function, division + import urwid -from . import signals + +from mitmproxy.console import signals class Window(urwid.Frame): diff --git a/mitmproxy/contentviews.py b/mitmproxy/contentviews.py index 373c9514..87cb2aa0 100644 --- a/mitmproxy/contentviews.py +++ b/mitmproxy/contentviews.py @@ -12,27 +12,31 @@ use. For HTTP, the message headers are passed as the ``headers`` keyword argumen requests, the query parameters are passed as the ``query`` keyword argument. """ -from __future__ import (absolute_import, print_function, division) -from six.moves import cStringIO as StringIO +from __future__ import absolute_import, print_function, division + +import datetime import json import logging import subprocess import sys -import lxml.html -import lxml.etree -import datetime -from PIL import Image -from PIL.ExifTags import TAGS + import html2text +import lxml.etree +import lxml.html import six -from netlib.odict import ODict -from netlib import encoding, http +from PIL import ExifTags +from PIL import Image +from six.moves import cStringIO as StringIO + +import mitmproxy.utils +from mitmproxy import exceptions +from mitmproxy.contrib import jsbeautifier +from mitmproxy.contrib.wbxml import ASCommandResponse +from netlib import encoding +from netlib import http +from netlib import odict from netlib.http import url -from netlib.utils import clean_bin, hexdump -from . import utils -from .exceptions import ContentViewException -from .contrib import jsbeautifier -from .contrib.wbxml.ASCommandResponse import ASCommandResponse +import netlib.utils try: import pyamf @@ -125,11 +129,11 @@ class ViewAuto(View): ct = "%s/%s" % (ct[0], ct[1]) if ct in content_types_map: return content_types_map[ct][0](data, **metadata) - elif utils.isXML(data): + elif mitmproxy.utils.isXML(data): return get("XML")(data, **metadata) if metadata.get("query"): return get("Query")(data, **metadata) - if data and utils.isMostlyBin(data): + if data and mitmproxy.utils.isMostlyBin(data): return get("Hex")(data) if not data: return "No content", [] @@ -152,7 +156,7 @@ class ViewHex(View): @staticmethod def _format(data): - for offset, hexa, s in hexdump(data): + for offset, hexa, s in netlib.utils.hexdump(data): yield [ ("offset", offset + " "), ("text", hexa + " "), @@ -211,7 +215,7 @@ class ViewJSON(View): content_types = ["application/json"] def __call__(self, data, **metadata): - pretty_json = utils.pretty_json(data) + pretty_json = mitmproxy.utils.pretty_json(data) if pretty_json: return "JSON", format_text(pretty_json) @@ -222,7 +226,7 @@ class ViewHTML(View): content_types = ["text/html"] def __call__(self, data, **metadata): - if utils.isXML(data): + if mitmproxy.utils.isXML(data): parser = lxml.etree.HTMLParser( strip_cdata=True, remove_blank_text=True @@ -259,7 +263,7 @@ class ViewURLEncoded(View): def __call__(self, data, **metadata): d = url.decode(data) - return "URLEncoded form", format_dict(ODict(d)) + return "URLEncoded form", format_dict(odict.ODict(d)) class ViewMultipart(View): @@ -270,7 +274,7 @@ class ViewMultipart(View): @staticmethod def _format(v): yield [("highlight", "Form data:\n")] - for message in format_dict(ODict(v)): + for message in format_dict(odict.ODict(v)): yield message def __call__(self, data, **metadata): @@ -415,11 +419,11 @@ class ViewImage(View): ex = img._getexif() if ex: for i in sorted(ex.keys()): - tag = TAGS.get(i, i) + tag = ExifTags.TAGS.get(i, i) parts.append( (str(tag), str(ex[i])) ) - fmt = format_dict(ODict(parts)) + fmt = format_dict(odict.ODict(parts)) return "%s image" % img.format, fmt @@ -490,7 +494,7 @@ class ViewWBXML(View): def __call__(self, data, **metadata): try: - parser = ASCommandResponse(data) + parser = ASCommandResponse.ASCommandResponse(data) parsedContent = parser.xmlString if parsedContent: return "WBXML", format_text(parsedContent) @@ -519,12 +523,12 @@ def add(view): # TODO: auto-select a different name (append an integer?) for i in views: if i.name == view.name: - raise ContentViewException("Duplicate view: " + view.name) + raise exceptions.ContentViewException("Duplicate view: " + view.name) # TODO: the UI should auto-prompt for a replacement shortcut for prompt in view_prompts: if prompt[1] == view.prompt[1]: - raise ContentViewException("Duplicate view shortcut: " + view.prompt[1]) + raise exceptions.ContentViewException("Duplicate view shortcut: " + view.prompt[1]) views.append(view) @@ -577,9 +581,9 @@ def safe_to_print(lines, encoding="utf8"): clean_line = [] for (style, text) in line: try: - text = clean_bin(text.decode(encoding, "strict")) + text = netlib.utils.clean_bin(text.decode(encoding, "strict")) except UnicodeDecodeError: - text = clean_bin(text).decode(encoding, "strict") + text = netlib.utils.clean_bin(text).decode(encoding, "strict") clean_line.append((style, text)) yield clean_line @@ -611,8 +615,8 @@ def get_content_view(viewmode, data, **metadata): # Third-party viewers can fail in unexpected ways... except Exception as e: six.reraise( - ContentViewException, - ContentViewException(str(e)), + exceptions.ContentViewException, + exceptions.ContentViewException(str(e)), sys.exc_info()[2] ) if not ret: diff --git a/mitmproxy/controller.py b/mitmproxy/controller.py index a9e101eb..1498c3ad 100644 --- a/mitmproxy/controller.py +++ b/mitmproxy/controller.py @@ -1,9 +1,11 @@ -from __future__ import absolute_import -from six.moves import queue -import threading +from __future__ import absolute_import, print_function, division + import functools +import threading + +from six.moves import queue -from . import exceptions +from mitmproxy import exceptions Events = frozenset([ "clientconnect", diff --git a/mitmproxy/dump.py b/mitmproxy/dump.py index 0f54b4d4..f5d6725c 100644 --- a/mitmproxy/dump.py +++ b/mitmproxy/dump.py @@ -1,13 +1,19 @@ -from __future__ import absolute_import, print_function -import traceback +from __future__ import absolute_import, print_function, division + +import itertools import sys +import traceback + import click -import itertools -from netlib import tcp, human -from netlib.utils import bytes_to_escaped_str -from . import flow, filt, contentviews, controller -from .exceptions import ContentViewException, FlowReadException, ScriptException +from mitmproxy import contentviews +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import filt +from mitmproxy import flow +from netlib import human +from netlib import tcp +from netlib import utils class DumpError(Exception): @@ -127,13 +133,13 @@ class DumpMaster(flow.FlowMaster): for command in scripts: try: self.load_script(command, use_reloader=True) - except ScriptException as e: + except exceptions.ScriptException as e: raise DumpError(str(e)) if options.rfile: try: self.load_flows_file(options.rfile) - except FlowReadException as v: + except exceptions.FlowReadException as v: self.add_event("Flow file corrupted.", "error") raise DumpError(v) @@ -147,7 +153,7 @@ class DumpMaster(flow.FlowMaster): """ try: return flow.read_flows_from_paths(paths) - except FlowReadException as e: + except exceptions.FlowReadException as e: raise DumpError(str(e)) def add_event(self, e, level="info"): @@ -175,8 +181,8 @@ class DumpMaster(flow.FlowMaster): if self.o.flow_detail >= 2: headers = "\r\n".join( "{}: {}".format( - click.style(bytes_to_escaped_str(k), fg="blue", bold=True), - click.style(bytes_to_escaped_str(v), fg="blue")) + click.style(utils.bytes_to_escaped_str(k), fg="blue", bold=True), + click.style(utils.bytes_to_escaped_str(v), fg="blue")) for k, v in message.headers.fields ) self.echo(headers, indent=4) @@ -192,7 +198,7 @@ class DumpMaster(flow.FlowMaster): message.content, headers=message.headers ) - except ContentViewException: + except exceptions.ContentViewException: s = "Content viewer failed: \n" + traceback.format_exc() self.add_event(s, "debug") type, lines = contentviews.get_content_view( @@ -238,7 +244,7 @@ class DumpMaster(flow.FlowMaster): stickycookie = "" if flow.client_conn: - client = click.style(bytes_to_escaped_str(flow.client_conn.address.host), bold=True) + client = click.style(utils.bytes_to_escaped_str(flow.client_conn.address.host), bold=True) else: client = click.style("[replay]", fg="yellow", bold=True) @@ -247,12 +253,12 @@ class DumpMaster(flow.FlowMaster): GET="green", DELETE="red" ).get(method.upper(), "magenta") - method = click.style(bytes_to_escaped_str(method), fg=method_color, bold=True) + method = click.style(utils.bytes_to_escaped_str(method), fg=method_color, bold=True) if self.showhost: url = flow.request.pretty_url else: url = flow.request.url - url = click.style(bytes_to_escaped_str(url), bold=True) + url = click.style(utils.bytes_to_escaped_str(url), bold=True) httpversion = "" if flow.request.http_version not in ("HTTP/1.1", "HTTP/1.0"): @@ -282,7 +288,7 @@ class DumpMaster(flow.FlowMaster): elif 400 <= code < 600: code_color = "red" code = click.style(str(code), fg=code_color, bold=True, blink=(code == 418)) - reason = click.style(bytes_to_escaped_str(flow.response.reason), fg=code_color, bold=True) + reason = click.style(utils.bytes_to_escaped_str(flow.response.reason), fg=code_color, bold=True) if flow.response.content is None: size = "(content missing)" diff --git a/mitmproxy/exceptions.py b/mitmproxy/exceptions.py index b1d2c03a..d97b9498 100644 --- a/mitmproxy/exceptions.py +++ b/mitmproxy/exceptions.py @@ -5,11 +5,10 @@ Every Exception mitmproxy raises shall be a subclass of ProxyException. See also: http://lucumr.pocoo.org/2014/10/16/on-error-handling/ """ -from __future__ import (absolute_import, print_function, division) - -import traceback +from __future__ import absolute_import, print_function, division import sys +import traceback class ProxyException(Exception): diff --git a/mitmproxy/filt.py b/mitmproxy/filt.py index 6228d364..d98e3749 100644 --- a/mitmproxy/filt.py +++ b/mitmproxy/filt.py @@ -31,9 +31,11 @@ ~c CODE Response code. rex Equivalent to ~u rex """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, division + import re import sys + import pyparsing as pp diff --git a/mitmproxy/flow/export.py b/mitmproxy/flow/export.py index d71ac609..97cee984 100644 --- a/mitmproxy/flow/export.py +++ b/mitmproxy/flow/export.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, print_function, division + import json import re from textwrap import dedent diff --git a/mitmproxy/flow/io.py b/mitmproxy/flow/io.py index f31c8e5b..cd3d9986 100644 --- a/mitmproxy/flow/io.py +++ b/mitmproxy/flow/io.py @@ -1,7 +1,10 @@ +from __future__ import absolute_import, print_function, division + import os -from mitmproxy import tnetstring, models -from mitmproxy.exceptions import FlowReadException +from mitmproxy import exceptions +from mitmproxy import models +from mitmproxy import tnetstring from mitmproxy.flow import io_compat @@ -38,17 +41,17 @@ class FlowReader: try: data = io_compat.migrate_flow(data) except ValueError as e: - raise FlowReadException(str(e)) + raise exceptions.FlowReadException(str(e)) if can_tell: off = self.fo.tell() if data["type"] not in models.FLOW_TYPES: - raise FlowReadException("Unknown flow type: {}".format(data["type"])) + raise exceptions.FlowReadException("Unknown flow type: {}".format(data["type"])) yield models.FLOW_TYPES[data["type"]].from_state(data) except ValueError: # Error is due to EOF if can_tell and self.fo.tell() == off and self.fo.read() == '': return - raise FlowReadException("Invalid data format.") + raise exceptions.FlowReadException("Invalid data format.") class FilteredFlowWriter: @@ -79,5 +82,5 @@ def read_flows_from_paths(paths): with open(path, "rb") as f: flows.extend(FlowReader(f).stream()) except IOError as e: - raise FlowReadException(e.strerror) + raise exceptions.FlowReadException(e.strerror) return flows diff --git a/mitmproxy/flow/master.py b/mitmproxy/flow/master.py index e0d2c51e..a198018e 100644 --- a/mitmproxy/flow/master.py +++ b/mitmproxy/flow/master.py @@ -1,16 +1,22 @@ +from __future__ import absolute_import, print_function, division + import os import sys from typing import List, Optional, Set # noqa -from mitmproxy import controller, script, filt, models -from mitmproxy.exceptions import FlowReadException, Kill -from mitmproxy.flow import io, modules +import netlib.exceptions +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import filt +from mitmproxy import models +from mitmproxy import script +from mitmproxy.flow import io +from mitmproxy.flow import modules from mitmproxy.onboarding import app -from mitmproxy.protocol.http_replay import RequestReplayThread +from mitmproxy.protocol import http_replay from mitmproxy.proxy.config import HostMatcher from netlib import utils -from netlib.exceptions import HttpException class FlowMaster(controller.Master): @@ -311,7 +317,7 @@ class FlowMaster(controller.Master): freader = io.FlowReader(f) return self.load_flows(freader) except IOError as v: - raise FlowReadException(v.strerror) + raise exceptions.FlowReadException(v.strerror) def process_new_request(self, f): if self.stickycookie_state: @@ -351,7 +357,7 @@ class FlowMaster(controller.Master): f.response = None f.error = None self.process_new_request(f) - rt = RequestReplayThread( + rt = http_replay.RequestReplayThread( self.server.config, f, self.event_queue if run_scripthooks else False, @@ -405,7 +411,7 @@ class FlowMaster(controller.Master): ) if err: self.add_event("Error in wsgi app. %s" % err, "error") - f.reply(Kill) + f.reply(exceptions.Kill) return if f not in self.state.flows: # don't add again on replay self.state.add_flow(f) @@ -421,8 +427,8 @@ class FlowMaster(controller.Master): try: if self.stream_large_bodies: self.stream_large_bodies.run(f, False) - except HttpException: - f.reply(Kill) + except netlib.exceptions.HttpException: + f.reply(exceptions.Kill) return self.run_script_hook("responseheaders", f) return f diff --git a/mitmproxy/flow/modules.py b/mitmproxy/flow/modules.py index 438c5a21..601ebfce 100644 --- a/mitmproxy/flow/modules.py +++ b/mitmproxy/flow/modules.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import, print_function, division + import collections import hashlib import re @@ -5,9 +7,12 @@ import re from six.moves import http_cookiejar from six.moves import urllib -from mitmproxy import version, filt, controller +from mitmproxy import controller +from mitmproxy import filt +from mitmproxy import version from netlib import wsgi -from netlib.http import http1, cookies +from netlib.http import cookies +from netlib.http import http1 class AppRegistry: diff --git a/mitmproxy/flow/state.py b/mitmproxy/flow/state.py index 16e79542..4287d77b 100644 --- a/mitmproxy/flow/state.py +++ b/mitmproxy/flow/state.py @@ -1,9 +1,12 @@ +from __future__ import absolute_import, print_function, division + from abc import abstractmethod, ABCMeta import six from typing import List # noqa -from mitmproxy import models, filt # noqa +from mitmproxy import filt +from mitmproxy import models # noqa @six.add_metaclass(ABCMeta) diff --git a/mitmproxy/main.py b/mitmproxy/main.py index d44c257e..b73966ba 100644 --- a/mitmproxy/main.py +++ b/mitmproxy/main.py @@ -1,13 +1,16 @@ -from __future__ import print_function, absolute_import +from __future__ import absolute_import, print_function, division + import os import signal import sys + from six.moves import _thread # PY3: We only need _thread.error, which is an alias of RuntimeError in 3.3+ -from netlib.version_check import check_pyopenssl_version -from . import cmdline -from .exceptions import ServerException -from .proxy.server import DummyServer, ProxyServer -from .proxy.config import process_proxy_options + +from mitmproxy import cmdline +from mitmproxy import exceptions +from mitmproxy.proxy import config +from mitmproxy.proxy import server +from netlib import version_check def assert_utf8_env(): @@ -28,11 +31,11 @@ def assert_utf8_env(): def get_server(dummy_server, options): if dummy_server: - return DummyServer(options) + return server.DummyServer(options) else: try: - return ProxyServer(options) - except ServerException as v: + return server.ProxyServer(options) + except exceptions.ServerException as v: print(str(v), file=sys.stderr) sys.exit(1) @@ -44,7 +47,7 @@ def mitmproxy(args=None): # pragma: no cover sys.exit(1) from . import console - check_pyopenssl_version() + version_check.check_pyopenssl_version() assert_utf8_env() parser = cmdline.mitmproxy() @@ -52,7 +55,7 @@ def mitmproxy(args=None): # pragma: no cover if options.quiet: options.verbose = 0 - proxy_config = process_proxy_options(parser, options) + proxy_config = cmdline.process_proxy_options(parser, options) console_options = console.Options(**cmdline.get_common_options(options)) console_options.palette = options.palette console_options.palette_transparent = options.palette_transparent @@ -74,7 +77,7 @@ def mitmproxy(args=None): # pragma: no cover def mitmdump(args=None): # pragma: no cover from . import dump - check_pyopenssl_version() + version_check.check_pyopenssl_version() parser = cmdline.mitmdump() options = parser.parse_args(args) @@ -82,7 +85,7 @@ def mitmdump(args=None): # pragma: no cover options.verbose = 0 options.flow_detail = 0 - proxy_config = process_proxy_options(parser, options) + proxy_config = config.process_proxy_options(parser, options) dump_options = dump.Options(**cmdline.get_common_options(options)) dump_options.flow_detail = options.flow_detail dump_options.keepserving = options.keepserving @@ -108,7 +111,7 @@ def mitmdump(args=None): # pragma: no cover def mitmweb(args=None): # pragma: no cover from . import web - check_pyopenssl_version() + version_check.check_pyopenssl_version() parser = cmdline.mitmweb() @@ -116,7 +119,7 @@ def mitmweb(args=None): # pragma: no cover if options.quiet: options.verbose = 0 - proxy_config = process_proxy_options(parser, options) + proxy_config = config.process_proxy_options(parser, options) web_options = web.Options(**cmdline.get_common_options(options)) web_options.intercept = options.intercept web_options.wdebug = options.wdebug diff --git a/mitmproxy/models/__init__.py b/mitmproxy/models/__init__.py index 3d9d9dae..ca813567 100644 --- a/mitmproxy/models/__init__.py +++ b/mitmproxy/models/__init__.py @@ -1,12 +1,12 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division +from netlib.http import decoded +from .connections import ClientConnection, ServerConnection +from .flow import Flow, Error from .http import ( HTTPFlow, HTTPRequest, HTTPResponse, Headers, make_error_response, make_connect_request, make_connect_response, expect_continue_response ) -from netlib.http import decoded -from .connections import ClientConnection, ServerConnection -from .flow import Flow, Error from .tcp import TCPFlow FLOW_TYPES = dict( diff --git a/mitmproxy/models/connections.py b/mitmproxy/models/connections.py index 24cdff74..6347f488 100644 --- a/mitmproxy/models/connections.py +++ b/mitmproxy/models/connections.py @@ -1,12 +1,14 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division import copy import os import six -from netlib import tcp, certutils -from .. import stateobject, utils +from mitmproxy import stateobject +from mitmproxy import utils +from netlib import certutils +from netlib import tcp class ClientConnection(tcp.BaseHandler, stateobject.StateObject): diff --git a/mitmproxy/models/flow.py b/mitmproxy/models/flow.py index 8797fcd8..7b9ec030 100644 --- a/mitmproxy/models/flow.py +++ b/mitmproxy/models/flow.py @@ -1,10 +1,14 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import copy import uuid -from .. import stateobject, utils, version -from .connections import ClientConnection, ServerConnection -from ..exceptions import Kill +from mitmproxy import exceptions +from mitmproxy import stateobject +from mitmproxy import utils +from mitmproxy import version +from mitmproxy.models.connections import ClientConnection +from mitmproxy.models.connections import ServerConnection class Error(stateobject.StateObject): @@ -151,7 +155,7 @@ class Flow(stateobject.StateObject): """ self.error = Error("Connection killed") self.intercepted = False - self.reply(Kill) + self.reply(exceptions.Kill) master.error(self) def intercept(self, master): diff --git a/mitmproxy/models/http.py b/mitmproxy/models/http.py index 43618ef8..a32124ac 100644 --- a/mitmproxy/models/http.py +++ b/mitmproxy/models/http.py @@ -1,11 +1,15 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import cgi +from mitmproxy import version +from mitmproxy.models.flow import Flow from netlib import encoding -from netlib.http import status_codes, Headers, Request, Response +from netlib.http import Headers +from netlib.http import Request +from netlib.http import Response +from netlib.http import status_codes from netlib.tcp import Address -from .. import version -from .flow import Flow class MessageMixin(object): diff --git a/mitmproxy/models/tcp.py b/mitmproxy/models/tcp.py index c7cfb9f8..e33475c2 100644 --- a/mitmproxy/models/tcp.py +++ b/mitmproxy/models/tcp.py @@ -1,8 +1,11 @@ +from __future__ import absolute_import, print_function, division + import time + from typing import List import netlib.basetypes -from .flow import Flow +from mitmproxy.models.flow import Flow class TCPMessage(netlib.basetypes.Serializable): diff --git a/mitmproxy/onboarding/app.py b/mitmproxy/onboarding/app.py index ff5ed63c..f93b9982 100644 --- a/mitmproxy/onboarding/app.py +++ b/mitmproxy/onboarding/app.py @@ -1,12 +1,13 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division + import os + +import tornado.template import tornado.web import tornado.wsgi -import tornado.template - -from .. import utils -from ..proxy import config +from mitmproxy import utils +from mitmproxy.proxy import config loader = tornado.template.Loader(utils.pkg_data.path("onboarding/templates")) diff --git a/mitmproxy/platform/osx.py b/mitmproxy/platform/osx.py index 3cd4bc66..b16c1861 100644 --- a/mitmproxy/platform/osx.py +++ b/mitmproxy/platform/osx.py @@ -1,4 +1,5 @@ import subprocess + import pf """ diff --git a/mitmproxy/platform/windows.py b/mitmproxy/platform/windows.py index 0a810908..576516e2 100644 --- a/mitmproxy/platform/windows.py +++ b/mitmproxy/platform/windows.py @@ -1,18 +1,17 @@ -import configargparse -from six.moves import cPickle as pickle -from ctypes import byref, windll, Structure -from ctypes.wintypes import DWORD +import collections +import ctypes +import ctypes.wintypes import os import socket -from six.moves import socketserver import struct import threading import time -from collections import OrderedDict - -from pydivert.windivert import WinDivert -from pydivert.enum import Direction, Layer, Flag +import configargparse +from pydivert import enum +from pydivert import windivert +from six.moves import cPickle as pickle +from six.moves import socketserver PROXY_API_PORT = 8085 @@ -91,22 +90,22 @@ ERROR_INSUFFICIENT_BUFFER = 0x7A # http://msdn.microsoft.com/en-us/library/windows/desktop/bb485761(v=vs.85).aspx -class MIB_TCPROW2(Structure): +class MIB_TCPROW2(ctypes.Structure): _fields_ = [ - ('dwState', DWORD), - ('dwLocalAddr', DWORD), - ('dwLocalPort', DWORD), - ('dwRemoteAddr', DWORD), - ('dwRemotePort', DWORD), - ('dwOwningPid', DWORD), - ('dwOffloadState', DWORD) + ('dwState', ctypes.wintypes.DWORD), + ('dwLocalAddr', ctypes.wintypes.DWORD), + ('dwLocalPort', ctypes.wintypes.DWORD), + ('dwRemoteAddr', ctypes.wintypes.DWORD), + ('dwRemotePort', ctypes.wintypes.DWORD), + ('dwOwningPid', ctypes.wintypes.DWORD), + ('dwOffloadState', ctypes.wintypes.DWORD) ] # http://msdn.microsoft.com/en-us/library/windows/desktop/bb485772(v=vs.85).aspx def MIB_TCPTABLE2(size): - class _MIB_TCPTABLE2(Structure): - _fields_ = [('dwNumEntries', DWORD), + class _MIB_TCPTABLE2(ctypes.Structure): + _fields_ = [('dwNumEntries', ctypes.wintypes.DWORD), ('table', MIB_TCPROW2 * size)] return _MIB_TCPTABLE2() @@ -192,13 +191,13 @@ class TransparentProxy(object): self.proxy_addr, self.proxy_port = proxy_addr, proxy_port self.connection_cache_size = cache_size - self.client_server_map = OrderedDict() + self.client_server_map = collections.OrderedDict() self.api = APIServer(self, (api_host, api_port), APIRequestHandler) self.api_thread = threading.Thread(target=self.api.serve_forever) self.api_thread.daemon = True - self.driver = WinDivert() + self.driver = windivert.WinDivert() self.driver.register() self.request_filter = custom_filter or " or ".join( @@ -212,7 +211,7 @@ class TransparentProxy(object): self.addr_pid_map = dict() self.trusted_pids = set() self.tcptable2 = MIB_TCPTABLE2(0) - self.tcptable2_size = DWORD(0) + self.tcptable2_size = ctypes.wintypes.DWORD(0) self.request_local_handle = None self.request_local_thread = threading.Thread(target=self.request_local) self.request_local_thread.daemon = True @@ -244,23 +243,23 @@ class TransparentProxy(object): # real gateway if they are on the same network. self.icmp_handle = self.driver.open_handle( filter="icmp", - layer=Layer.NETWORK, - flags=Flag.DROP) + layer=enum.Layer.NETWORK, + flags=enum.Flag.DROP) self.response_handle = self.driver.open_handle( filter=self.response_filter, - layer=Layer.NETWORK) + layer=enum.Layer.NETWORK) self.response_thread.start() if self.mode == "forward" or self.mode == "both": self.request_forward_handle = self.driver.open_handle( filter=self.request_filter, - layer=Layer.NETWORK_FORWARD) + layer=enum.Layer.NETWORK_FORWARD) self.request_forward_thread.start() if self.mode == "local" or self.mode == "both": self.request_local_handle = self.driver.open_handle( filter=self.request_filter, - layer=Layer.NETWORK) + layer=enum.Layer.NETWORK) self.request_local_thread.start() def shutdown(self): @@ -288,9 +287,9 @@ class TransparentProxy(object): raise def fetch_pids(self): - ret = windll.iphlpapi.GetTcpTable2( - byref( - self.tcptable2), byref( + ret = ctypes.windll.iphlpapi.GetTcpTable2( + ctypes.byref( + self.tcptable2), ctypes.byref( self.tcptable2_size), 0) if ret == ERROR_INSUFFICIENT_BUFFER: self.tcptable2 = MIB_TCPTABLE2(self.tcptable2_size.value) @@ -352,7 +351,7 @@ class TransparentProxy(object): self.client_server_map[client] = server packet.dst_addr, packet.dst_port = self.proxy_addr, self.proxy_port - metadata.direction = Direction.INBOUND + metadata.direction = enum.Direction.INBOUND packet = self.driver.update_packet_checksums(packet) # Use any handle thats on the NETWORK layer - request_local may be diff --git a/mitmproxy/protocol/__init__.py b/mitmproxy/protocol/__init__.py index 3d9fa7d4..510cd195 100644 --- a/mitmproxy/protocol/__init__.py +++ b/mitmproxy/protocol/__init__.py @@ -25,15 +25,16 @@ Another subtle design goal of this architecture is that upstream connections sho as late as possible; this makes server replay without any outgoing connections possible. """ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + from .base import Layer, ServerConnectionMixin -from .tls import TlsLayer -from .tls import is_tls_record_magic -from .tls import TlsClientHello from .http import UpstreamConnectLayer from .http1 import Http1Layer from .http2 import Http2Layer from .rawtcp import RawTCPLayer +from .tls import TlsClientHello +from .tls import TlsLayer +from .tls import is_tls_record_magic __all__ = [ "Layer", "ServerConnectionMixin", diff --git a/mitmproxy/protocol/base.py b/mitmproxy/protocol/base.py index c8e58d1b..11773385 100644 --- a/mitmproxy/protocol/base.py +++ b/mitmproxy/protocol/base.py @@ -1,11 +1,12 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import sys import six -from ..models import ServerConnection -from ..exceptions import ProtocolException -from netlib.exceptions import TcpException +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import models class _LayerCodeCompletion(object): @@ -113,7 +114,7 @@ class ServerConnectionMixin(object): def __init__(self, server_address=None): super(ServerConnectionMixin, self).__init__() - self.server_conn = ServerConnection(server_address, (self.config.host, 0)) + self.server_conn = models.ServerConnection(server_address, (self.config.host, 0)) self.__check_self_connect() def __check_self_connect(self): @@ -128,7 +129,7 @@ class ServerConnectionMixin(object): address.host in ("localhost", "127.0.0.1", "::1") ) if self_connect: - raise ProtocolException( + raise exceptions.ProtocolException( "Invalid server address: {}\r\n" "The proxy shall not connect to itself.".format(repr(address)) ) @@ -154,7 +155,7 @@ class ServerConnectionMixin(object): self.server_conn.finish() self.server_conn.close() self.channel.tell("serverdisconnect", self.server_conn) - self.server_conn = ServerConnection(address, (source_address.host, 0)) + self.server_conn = models.ServerConnection(address, (source_address.host, 0)) def connect(self): """ @@ -165,15 +166,15 @@ class ServerConnectionMixin(object): ~mitmproxy.exceptions.ProtocolException: if the connection could not be established. """ if not self.server_conn.address: - raise ProtocolException("Cannot connect to server, no server address given.") + raise exceptions.ProtocolException("Cannot connect to server, no server address given.") self.log("serverconnect", "debug", [repr(self.server_conn.address)]) self.channel.ask("serverconnect", self.server_conn) try: self.server_conn.connect() - except TcpException as e: + except netlib.exceptions.TcpException as e: six.reraise( - ProtocolException, - ProtocolException( + exceptions.ProtocolException, + exceptions.ProtocolException( "Server connection to {} failed: {}".format( repr(self.server_conn.address), str(e) ) diff --git a/mitmproxy/protocol/http.py b/mitmproxy/protocol/http.py index d9111303..ae03ab7f 100644 --- a/mitmproxy/protocol/http.py +++ b/mitmproxy/protocol/http.py @@ -1,30 +1,21 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division import sys import traceback + +import h2.exceptions import six +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import models +from mitmproxy import utils +from mitmproxy.protocol import base +from netlib import http from netlib import tcp -from netlib.exceptions import HttpException, HttpReadDisconnect, NetlibException -from netlib.http import Headers - -from h2.exceptions import H2Error - -from .. import utils -from ..exceptions import HttpProtocolException, Http2ProtocolException, ProtocolException -from ..models import ( - HTTPFlow, - HTTPResponse, - make_error_response, - make_connect_response, - Error, - expect_continue_response -) - -from .base import Layer -class _HttpTransmissionLayer(Layer): +class _HttpTransmissionLayer(base.Layer): def read_request(self): raise NotImplementedError() @@ -51,7 +42,7 @@ class _HttpTransmissionLayer(Layer): def send_response(self, response): if response.content is None: - raise HttpException("Cannot assemble flow with missing content") + raise netlib.exceptions.HttpException("Cannot assemble flow with missing content") self.send_response_headers(response) self.send_response_body(response, [response.content]) @@ -89,7 +80,7 @@ class ConnectServerConnection(object): __nonzero__ = __bool__ -class UpstreamConnectLayer(Layer): +class UpstreamConnectLayer(base.Layer): def __init__(self, ctx, connect_request): super(UpstreamConnectLayer, self).__init__(ctx) @@ -107,7 +98,7 @@ class UpstreamConnectLayer(Layer): self.send_request(self.connect_request) resp = self.read_response(self.connect_request) if resp.status_code != 200: - raise ProtocolException("Reconnect: Upstream server refuses CONNECT request") + raise exceptions.ProtocolException("Reconnect: Upstream server refuses CONNECT request") def connect(self): if not self.server_conn: @@ -129,7 +120,7 @@ class UpstreamConnectLayer(Layer): self.server_conn.address = address -class HttpLayer(Layer): +class HttpLayer(base.Layer): def __init__(self, ctx, mode): super(HttpLayer, self).__init__(ctx) @@ -166,16 +157,16 @@ class HttpLayer(Layer): self.handle_regular_mode_connect(request) return - except HttpReadDisconnect: + except netlib.exceptions.HttpReadDisconnect: # don't throw an error for disconnects that happen before/between requests. return - except NetlibException as e: + except netlib.exceptions.NetlibException as e: self.send_error_response(400, repr(e)) - six.reraise(ProtocolException, ProtocolException( + six.reraise(exceptions.ProtocolException, exceptions.ProtocolException( "Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2]) try: - flow = HTTPFlow(self.client_conn, self.server_conn, live=self) + flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self) flow.request = request # set upstream auth if self.mode == "upstream" and self.config.upstream_auth is not None: @@ -210,16 +201,16 @@ class HttpLayer(Layer): self.handle_upstream_mode_connect(flow.request.copy()) return - except (ProtocolException, NetlibException) as e: + except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e: self.send_error_response(502, repr(e)) if not flow.response: - flow.error = Error(str(e)) + flow.error = models.Error(str(e)) self.channel.ask("error", flow) self.log(traceback.format_exc(), "debug") return else: - six.reraise(ProtocolException, ProtocolException( + six.reraise(exceptions.ProtocolException, exceptions.ProtocolException( "Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2]) finally: if flow: @@ -229,16 +220,16 @@ class HttpLayer(Layer): request = self.read_request() if request.headers.get("expect", "").lower() == "100-continue": # TODO: We may have to use send_response_headers for HTTP2 here. - self.send_response(expect_continue_response) + self.send_response(models.expect_continue_response) request.headers.pop("expect") request.body = b"".join(self.read_request_body(request)) return request def send_error_response(self, code, message): try: - response = make_error_response(code, message) + response = models.make_error_response(code, message) self.send_response(response) - except (NetlibException, H2Error, Http2ProtocolException): + except (netlib.exceptions.NetlibException, h2.exceptions.H2Error, exceptions.Http2ProtocolException): self.log(traceback.format_exc(), "debug") def change_upstream_proxy_server(self, address): @@ -249,7 +240,7 @@ class HttpLayer(Layer): def handle_regular_mode_connect(self, request): self.set_server((request.host, request.port)) - self.send_response(make_connect_response(request.data.http_version)) + self.send_response(models.make_connect_response(request.data.http_version)) layer = self.ctx.next_layer(self) layer() @@ -283,7 +274,7 @@ class HttpLayer(Layer): try: get_response() - except NetlibException as e: + except netlib.exceptions.NetlibException as e: self.log( "server communication error: %s" % repr(e), level="debug" @@ -300,9 +291,9 @@ class HttpLayer(Layer): # > read (100-n)% of large request # > send large request upstream - if isinstance(e, Http2ProtocolException): + if isinstance(e, exceptions.Http2ProtocolException): # do not try to reconnect for HTTP2 - raise ProtocolException("First and only attempt to get response via HTTP2 failed.") + raise exceptions.ProtocolException("First and only attempt to get response via HTTP2 failed.") self.disconnect() self.connect() @@ -345,7 +336,7 @@ class HttpLayer(Layer): flow.request.scheme = "https" if self.__initial_server_tls else "http" request_reply = self.channel.ask("request", flow) - if isinstance(request_reply, HTTPResponse): + if isinstance(request_reply, models.HTTPResponse): flow.response = request_reply return @@ -365,7 +356,7 @@ class HttpLayer(Layer): if not self.server_conn: self.connect() if tls: - raise HttpProtocolException("Cannot change scheme in upstream proxy mode.") + raise exceptions.HttpProtocolException("Cannot change scheme in upstream proxy mode.") """ # This is a very ugly (untested) workaround to solve a very ugly problem. if self.server_conn and self.server_conn.tls_established and not ssl: @@ -383,7 +374,7 @@ class HttpLayer(Layer): def validate_request(self, request): if request.first_line_format == "absolute" and request.scheme != "http": - raise HttpException("Invalid request scheme: %s" % request.scheme) + raise netlib.exceptions.HttpException("Invalid request scheme: %s" % request.scheme) expected_request_forms = { "regular": ("authority", "absolute",), @@ -396,7 +387,7 @@ class HttpLayer(Layer): err_message = "Invalid HTTP request form (expected: %s, got: %s)" % ( " or ".join(allowed_request_forms), request.first_line_format ) - raise HttpException(err_message) + raise netlib.exceptions.HttpException(err_message) if self.mode == "regular" and request.first_line_format == "absolute": request.first_line_format = "relative" @@ -406,10 +397,10 @@ class HttpLayer(Layer): if self.config.authenticator.authenticate(request.headers): self.config.authenticator.clean(request.headers) else: - self.send_response(make_error_response( + self.send_response(models.make_error_response( 407, "Proxy Authentication Required", - Headers(**self.config.authenticator.auth_challenge_headers()) + http.Headers(**self.config.authenticator.auth_challenge_headers()) )) return False return True diff --git a/mitmproxy/protocol/http1.py b/mitmproxy/protocol/http1.py index 940a4c98..7055a7fd 100644 --- a/mitmproxy/protocol/http1.py +++ b/mitmproxy/protocol/http1.py @@ -1,13 +1,11 @@ -from __future__ import (absolute_import, print_function, division) - +from __future__ import absolute_import, print_function, division +from mitmproxy import models +from mitmproxy.protocol import http from netlib.http import http1 -from .http import _HttpTransmissionLayer, HttpLayer -from ..models import HTTPRequest, HTTPResponse - -class Http1Layer(_HttpTransmissionLayer): +class Http1Layer(http._HttpTransmissionLayer): def __init__(self, ctx, mode): super(Http1Layer, self).__init__(ctx) @@ -15,7 +13,7 @@ class Http1Layer(_HttpTransmissionLayer): def read_request(self): req = http1.read_request(self.client_conn.rfile, body_size_limit=self.config.body_size_limit) - return HTTPRequest.wrap(req) + return models.HTTPRequest.wrap(req) def read_request_body(self, request): expected_size = http1.expected_http_body_size(request) @@ -27,7 +25,7 @@ class Http1Layer(_HttpTransmissionLayer): def read_response_headers(self): resp = http1.read_response_head(self.server_conn.rfile) - return HTTPResponse.wrap(resp) + return models.HTTPResponse.wrap(resp) def read_response_body(self, request, response): expected_size = http1.expected_http_body_size(request, response) @@ -63,5 +61,5 @@ class Http1Layer(_HttpTransmissionLayer): return close_connection def __call__(self): - layer = HttpLayer(self, self.mode) + layer = http.HttpLayer(self, self.mode) layer() diff --git a/mitmproxy/protocol/http2.py b/mitmproxy/protocol/http2.py index 6ca78347..39512c8f 100644 --- a/mitmproxy/protocol/http2.py +++ b/mitmproxy/protocol/http2.py @@ -1,29 +1,27 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division import threading import time -from six.moves import queue - import traceback + +import h2.exceptions +import hyperframe import six -from h2.connection import H2Connection -from h2.exceptions import StreamClosedError +from h2 import connection from h2 import events -from hyperframe.frame import PriorityFrame - -from netlib.tcp import ssl_read_select -from netlib.exceptions import HttpException -from netlib.http import Headers -from netlib.http.http2 import framereader -import netlib.http.url +from six.moves import queue -from .base import Layer -from .http import _HttpTransmissionLayer, HttpLayer -from ..exceptions import ProtocolException, Http2ProtocolException -from ..models import HTTPRequest, HTTPResponse +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import models +from mitmproxy.protocol import base +from mitmproxy.protocol import http +import netlib.http +from netlib import tcp +from netlib.http import http2 -class SafeH2Connection(H2Connection): +class SafeH2Connection(connection.H2Connection): def __init__(self, conn, *args, **kwargs): super(SafeH2Connection, self).__init__(*args, **kwargs) @@ -46,7 +44,7 @@ class SafeH2Connection(H2Connection): with self.lock: try: self.reset_stream(stream_id, error_code) - except StreamClosedError: # pragma: no cover + except h2.exceptions.StreamClosedError: # pragma: no cover # stream is already closed - good pass self.conn.send(self.data_to_send()) @@ -59,7 +57,7 @@ class SafeH2Connection(H2Connection): def safe_send_headers(self, is_zombie, stream_id, headers): with self.lock: if is_zombie(): # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") self.send_headers(stream_id, headers.fields) self.conn.send(self.data_to_send()) @@ -70,7 +68,7 @@ class SafeH2Connection(H2Connection): self.lock.acquire() if is_zombie(): # pragma: no cover self.lock.release() - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") max_outbound_frame_size = self.max_outbound_frame_size frame_chunk = chunk[position:position + max_outbound_frame_size] if self.local_flow_control_window(stream_id) < len(frame_chunk): @@ -83,12 +81,12 @@ class SafeH2Connection(H2Connection): position += max_outbound_frame_size with self.lock: if is_zombie(): # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") self.end_stream(stream_id) self.conn.send(self.data_to_send()) -class Http2Layer(Layer): +class Http2Layer(base.Layer): def __init__(self, ctx, mode): super(Http2Layer, self).__init__(ctx) @@ -108,13 +106,13 @@ class Http2Layer(Layer): self.active_conns.append(self.server_conn.connection) def connect(self): # pragma: no cover - raise Http2ProtocolException("HTTP2 layer should already have a connection.") + raise exceptions.Http2ProtocolException("HTTP2 layer should already have a connection.") def set_server(self): # pragma: no cover - raise Http2ProtocolException("Cannot change server for HTTP2 connections.") + raise exceptions.Http2ProtocolException("Cannot change server for HTTP2 connections.") def disconnect(self): # pragma: no cover - raise Http2ProtocolException("Cannot dis- or reconnect in HTTP2 connections.") + raise exceptions.Http2ProtocolException("Cannot dis- or reconnect in HTTP2 connections.") def next_layer(self): # pragma: no cover # WebSockets over HTTP/2? @@ -135,19 +133,19 @@ class Http2Layer(Layer): eid = event.stream_id if isinstance(event, events.RequestReceived): - headers = Headers([[k, v] for k, v in event.headers]) + headers = netlib.http.Headers([[k, v] for k, v in event.headers]) self.streams[eid] = Http2SingleStreamLayer(self, eid, headers) self.streams[eid].timestamp_start = time.time() self.streams[eid].start() elif isinstance(event, events.ResponseReceived): - headers = Headers([[k, v] for k, v in event.headers]) + headers = netlib.http.Headers([[k, v] for k, v in event.headers]) self.streams[eid].queued_data_length = 0 self.streams[eid].timestamp_start = time.time() self.streams[eid].response_headers = headers self.streams[eid].response_arrived.set() elif isinstance(event, events.DataReceived): if self.config.body_size_limit and self.streams[eid].queued_data_length > self.config.body_size_limit: - raise HttpException("HTTP body too large. Limit is {}.".format(self.config.body_size_limit)) + raise netlib.exceptions.HttpException("HTTP body too large. Limit is {}.".format(self.config.body_size_limit)) self.streams[eid].data_queue.put(event.data) self.streams[eid].queued_data_length += len(event.data) source_conn.h2.safe_increment_flow_control(event.stream_id, event.flow_controlled_length) @@ -178,7 +176,7 @@ class Http2Layer(Layer): self.client_conn.h2.push_stream(parent_eid, event.pushed_stream_id, event.headers) self.client_conn.send(self.client_conn.h2.data_to_send()) - headers = Headers([[str(k), str(v)] for k, v in event.headers]) + headers = netlib.http.Headers([[str(k), str(v)] for k, v in event.headers]) headers['x-mitmproxy-pushed'] = 'true' self.streams[event.pushed_stream_id] = Http2SingleStreamLayer(self, event.pushed_stream_id, headers) self.streams[event.pushed_stream_id].timestamp_start = time.time() @@ -197,7 +195,7 @@ class Http2Layer(Layer): depends_on = self.streams[depends_on].server_stream_id # weight is between 1 and 256 (inclusive), but represented as uint8 (0 to 255) - frame = PriorityFrame(stream_id, depends_on, event.weight - 1, event.exclusive) + frame = hyperframe.frame.PriorityFrame(stream_id, depends_on, event.weight - 1, event.exclusive) self.server_conn.send(frame.serialize()) elif isinstance(event, events.TrailersReceived): raise NotImplementedError() @@ -226,7 +224,7 @@ class Http2Layer(Layer): self.client_conn.send(self.client_conn.h2.data_to_send()) while True: - r = ssl_read_select(self.active_conns, 1) + r = tcp.ssl_read_select(self.active_conns, 1) for conn in r: source_conn = self.client_conn if conn == self.client_conn.connection else self.server_conn other_conn = self.server_conn if conn == self.client_conn.connection else self.client_conn @@ -234,7 +232,7 @@ class Http2Layer(Layer): with source_conn.h2.lock: try: - raw_frame = b''.join(framereader.http2_read_raw_frame(source_conn.rfile)) + raw_frame = b''.join(http2.framereader.http2_read_raw_frame(source_conn.rfile)) except: # read frame failed: connection closed self._kill_all_streams() @@ -252,7 +250,7 @@ class Http2Layer(Layer): self._cleanup_streams() -class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): +class Http2SingleStreamLayer(http._HttpTransmissionLayer, threading.Thread): def __init__(self, ctx, stream_id, request_headers): super(Http2SingleStreamLayer, self).__init__(ctx, name="Thread-Http2SingleStreamLayer-{}".format(stream_id)) @@ -336,7 +334,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): data.append(self.request_data_queue.get()) data = b"".join(data) - return HTTPRequest( + return models.HTTPRequest( first_line_format, method, scheme, @@ -361,7 +359,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): with self.server_conn.h2.lock: # We must not assign a stream id if we are already a zombie. if self.zombie: # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") self.server_stream_id = self.server_conn.h2.get_next_available_stream_id() self.server_to_client_stream_ids[self.server_stream_id] = self.client_stream_id @@ -382,7 +380,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): message.body ) if self.zombie: # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") def read_response_headers(self): self.response_arrived.wait() @@ -391,7 +389,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): headers = self.response_headers.copy() headers.clear(":status") - return HTTPResponse( + return models.HTTPResponse( http_version=b"HTTP/2.0", status_code=status_code, reason='', @@ -412,7 +410,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): yield self.response_data_queue.get() return if self.zombie: # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") def send_response_headers(self, response): headers = response.headers.copy() @@ -423,7 +421,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): headers ) if self.zombie: # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") def send_response_body(self, _response, chunks): self.client_conn.h2.safe_send_body( @@ -432,7 +430,7 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): chunks ) if self.zombie: # pragma: no cover - raise Http2ProtocolException("Zombie Stream") + raise exceptions.Http2ProtocolException("Zombie Stream") def check_close_connection(self, flow): # This layer only handles a single stream. @@ -447,11 +445,11 @@ class Http2SingleStreamLayer(_HttpTransmissionLayer, threading.Thread): self() def __call__(self): - layer = HttpLayer(self, self.mode) + layer = http.HttpLayer(self, self.mode) try: layer() - except ProtocolException as e: + except exceptions.ProtocolException as e: self.log(repr(e), "info") self.log(traceback.format_exc(), "debug") diff --git a/mitmproxy/protocol/http_replay.py b/mitmproxy/protocol/http_replay.py index f7f27148..5928c0af 100644 --- a/mitmproxy/protocol/http_replay.py +++ b/mitmproxy/protocol/http_replay.py @@ -1,13 +1,14 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import threading import traceback -from mitmproxy.exceptions import ReplayException -from netlib.exceptions import HttpException, TcpException + +import netlib.exceptions +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import models from netlib.http import http1 -from ..controller import Channel -from ..models import Error, HTTPResponse, ServerConnection, make_connect_request -from ..exceptions import Kill # TODO: Doesn't really belong into mitmproxy.protocol... @@ -22,7 +23,7 @@ class RequestReplayThread(threading.Thread): """ self.config, self.flow = config, flow if event_queue: - self.channel = Channel(event_queue, should_exit) + self.channel = controller.Channel(event_queue, should_exit) else: self.channel = None super(RequestReplayThread, self).__init__() @@ -36,17 +37,17 @@ class RequestReplayThread(threading.Thread): # If we have a channel, run script hooks. if self.channel: request_reply = self.channel.ask("request", self.flow) - if isinstance(request_reply, HTTPResponse): + if isinstance(request_reply, models.HTTPResponse): self.flow.response = request_reply if not self.flow.response: # In all modes, we directly connect to the server displayed if self.config.mode == "upstream": server_address = self.config.upstream_server.address - server = ServerConnection(server_address, (self.config.host, 0)) + server = models.ServerConnection(server_address, (self.config.host, 0)) server.connect() if r.scheme == "https": - connect_request = make_connect_request((r.host, r.port)) + connect_request = models.make_connect_request((r.host, r.port)) server.wfile.write(http1.assemble_request(connect_request)) server.wfile.flush() resp = http1.read_response( @@ -55,7 +56,7 @@ class RequestReplayThread(threading.Thread): body_size_limit=self.config.body_size_limit ) if resp.status_code != 200: - raise ReplayException("Upstream server refuses CONNECT request") + raise exceptions.ReplayException("Upstream server refuses CONNECT request") server.establish_ssl( self.config.clientcerts, sni=self.flow.server_conn.sni @@ -65,7 +66,7 @@ class RequestReplayThread(threading.Thread): r.first_line_format = "absolute" else: server_address = (r.host, r.port) - server = ServerConnection(server_address, (self.config.host, 0)) + server = models.ServerConnection(server_address, (self.config.host, 0)) server.connect() if r.scheme == "https": server.establish_ssl( @@ -77,20 +78,20 @@ class RequestReplayThread(threading.Thread): server.wfile.write(http1.assemble_request(r)) server.wfile.flush() self.flow.server_conn = server - self.flow.response = HTTPResponse.wrap(http1.read_response( + self.flow.response = models.HTTPResponse.wrap(http1.read_response( server.rfile, r, body_size_limit=self.config.body_size_limit )) if self.channel: response_reply = self.channel.ask("response", self.flow) - if response_reply == Kill: - raise Kill() - except (ReplayException, HttpException, TcpException) as e: - self.flow.error = Error(str(e)) + if response_reply == exceptions.Kill: + raise exceptions.Kill() + except (exceptions.ReplayException, netlib.exceptions.NetlibException) as e: + self.flow.error = models.Error(str(e)) if self.channel: self.channel.ask("error", self.flow) - except Kill: + except exceptions.Kill: # Kill should only be raised if there's a channel in the # first place. from ..proxy.root_context import Log diff --git a/mitmproxy/protocol/rawtcp.py b/mitmproxy/protocol/rawtcp.py index 05342844..70486cc4 100644 --- a/mitmproxy/protocol/rawtcp.py +++ b/mitmproxy/protocol/rawtcp.py @@ -1,17 +1,17 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import socket from OpenSSL import SSL -from netlib.exceptions import TcpException - -from netlib.tcp import ssl_read_select -from ..models import Error -from ..models.tcp import TCPFlow, TCPMessage -from .base import Layer +import netlib.exceptions +import netlib.tcp +from mitmproxy import models +from mitmproxy.models import tcp +from mitmproxy.protocol import base -class RawTCPLayer(Layer): +class RawTCPLayer(base.Layer): chunk_size = 4096 def __init__(self, ctx, ignore=False): @@ -22,7 +22,7 @@ class RawTCPLayer(Layer): self.connect() if not self.ignore: - flow = TCPFlow(self.client_conn, self.server_conn, self) + flow = models.TCPFlow(self.client_conn, self.server_conn, self) self.channel.ask("tcp_open", flow) buf = memoryview(bytearray(self.chunk_size)) @@ -33,7 +33,7 @@ class RawTCPLayer(Layer): try: while not self.channel.should_exit.is_set(): - r = ssl_read_select(conns, 10) + r = netlib.tcp.ssl_read_select(conns, 10) for conn in r: dst = server if conn == client else client @@ -52,15 +52,15 @@ class RawTCPLayer(Layer): return continue - tcp_message = TCPMessage(dst == server, buf[:size].tobytes()) + tcp_message = tcp.TCPMessage(dst == server, buf[:size].tobytes()) if not self.ignore: flow.messages.append(tcp_message) self.channel.ask("tcp_message", flow) dst.sendall(tcp_message.content) - except (socket.error, TcpException, SSL.Error) as e: + except (socket.error, netlib.exceptions.TcpException, SSL.Error) as e: if not self.ignore: - flow.error = Error("TCP connection closed unexpectedly: {}".format(repr(e))) + flow.error = models.Error("TCP connection closed unexpectedly: {}".format(repr(e))) self.channel.tell("tcp_error", flow) finally: if not self.ignore: diff --git a/mitmproxy/protocol/tls.py b/mitmproxy/protocol/tls.py index e0699562..9f883b2b 100644 --- a/mitmproxy/protocol/tls.py +++ b/mitmproxy/protocol/tls.py @@ -1,16 +1,15 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division import struct import sys -from construct import ConstructError +import construct import six -from netlib.exceptions import InvalidCertificateException -from netlib.exceptions import TlsException -from ..contrib.tls._constructs import ClientHello -from ..exceptions import ProtocolException, TlsProtocolException, ClientHandshakeException -from .base import Layer +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy.contrib.tls import _constructs +from mitmproxy.protocol import base # taken from https://testssl.sh/openssl-rfc.mappping.html @@ -246,11 +245,11 @@ def get_client_hello(client_conn): while len(client_hello) < client_hello_size: record_header = client_conn.rfile.peek(offset + 5)[offset:] if not is_tls_record_magic(record_header) or len(record_header) != 5: - raise TlsProtocolException('Expected TLS record, got "%s" instead.' % record_header) + raise exceptions.TlsProtocolException('Expected TLS record, got "%s" instead.' % record_header) record_size = struct.unpack("!H", record_header[3:])[0] + 5 record_body = client_conn.rfile.peek(offset + record_size)[offset + 5:] if len(record_body) != record_size - 5: - raise TlsProtocolException("Unexpected EOF in TLS handshake: %s" % record_body) + raise exceptions.TlsProtocolException("Unexpected EOF in TLS handshake: %s" % record_body) client_hello += record_body offset += record_size client_hello_size = struct.unpack("!I", b'\x00' + client_hello[1:4])[0] + 4 @@ -260,7 +259,7 @@ def get_client_hello(client_conn): class TlsClientHello(object): def __init__(self, raw_client_hello): - self._client_hello = ClientHello.parse(raw_client_hello) + self._client_hello = _constructs.ClientHello.parse(raw_client_hello) def raw(self): return self._client_hello @@ -297,21 +296,23 @@ class TlsClientHello(object): """ try: raw_client_hello = get_client_hello(client_conn)[4:] # exclude handshake header. - except ProtocolException as e: - raise TlsProtocolException('Cannot read raw Client Hello: %s' % repr(e)) + except exceptions.ProtocolException as e: + raise exceptions.TlsProtocolException('Cannot read raw Client Hello: %s' % repr(e)) try: return cls(raw_client_hello) - except ConstructError as e: - raise TlsProtocolException('Cannot parse Client Hello: %s, Raw Client Hello: %s' % - (repr(e), raw_client_hello.encode("hex"))) + except construct.ConstructError as e: + raise exceptions.TlsProtocolException( + 'Cannot parse Client Hello: %s, Raw Client Hello: %s' % + (repr(e), raw_client_hello.encode("hex")) + ) def __repr__(self): return "TlsClientHello( sni: %s alpn_protocols: %s, cipher_suites: %s)" % \ (self.sni, self.alpn_protocols, self.cipher_suites) -class TlsLayer(Layer): +class TlsLayer(base.Layer): """ The TLS layer implements transparent TLS connections. @@ -345,7 +346,7 @@ class TlsLayer(Layer): # Peek into the connection, read the initial client hello and parse it to obtain SNI and ALPN values. try: self._client_hello = TlsClientHello.from_client_conn(self.client_conn) - except TlsProtocolException as e: + except exceptions.TlsProtocolException as e: self.log("Cannot parse Client Hello: %s" % repr(e), "error") # Do we need to do a server handshake now? @@ -490,10 +491,10 @@ class TlsLayer(Layer): # The reason for this might be difficult to find, so we try to peek here to see if it # raises ann error. self.client_conn.rfile.peek(1) - except TlsException as e: + except netlib.exceptions.TlsException as e: six.reraise( - ClientHandshakeException, - ClientHandshakeException( + exceptions.ClientHandshakeException, + exceptions.ClientHandshakeException( "Cannot establish TLS with client (sni: {sni}): {e}".format( sni=self._client_hello.sni, e=repr(e) ), @@ -544,7 +545,7 @@ class TlsLayer(Layer): (tls_cert_err['depth'], tls_cert_err['errno']), "error") self.log("Ignoring server verification error, continuing with connection", "error") - except InvalidCertificateException as e: + except netlib.exceptions.InvalidCertificateException as e: tls_cert_err = self.server_conn.ssl_verification_error self.log( "TLS verification failed for upstream server at depth %s with error: %s" % @@ -552,18 +553,18 @@ class TlsLayer(Layer): "error") self.log("Aborting connection attempt", "error") six.reraise( - TlsProtocolException, - TlsProtocolException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( + exceptions.TlsProtocolException, + exceptions.TlsProtocolException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( address=repr(self.server_conn.address), sni=self.server_sni, e=repr(e), )), sys.exc_info()[2] ) - except TlsException as e: + except netlib.exceptions.TlsException as e: six.reraise( - TlsProtocolException, - TlsProtocolException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( + exceptions.TlsProtocolException, + exceptions.TlsProtocolException("Cannot establish TLS with {address} (sni: {sni}): {e}".format( address=repr(self.server_conn.address), sni=self.server_sni, e=repr(e), diff --git a/mitmproxy/proxy/__init__.py b/mitmproxy/proxy/__init__.py index be7f5207..ada9fa12 100644 --- a/mitmproxy/proxy/__init__.py +++ b/mitmproxy/proxy/__init__.py @@ -1,8 +1,8 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -from .server import ProxyServer, DummyServer from .config import ProxyConfig from .root_context import RootContext, Log +from .server import ProxyServer, DummyServer __all__ = [ "ProxyServer", "DummyServer", diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py index 163e92dd..9246fe04 100644 --- a/mitmproxy/proxy/config.py +++ b/mitmproxy/proxy/config.py @@ -1,4 +1,5 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import collections import os import re @@ -6,11 +7,11 @@ import re import six from OpenSSL import SSL -from netlib import certutils, tcp, human +from mitmproxy import platform +from netlib import certutils +from netlib import human +from netlib import tcp from netlib.http import authentication -from netlib.tcp import Address, sslversion_choices - -from .. import platform CONF_BASENAME = "mitmproxy" CA_DIR = "~/.mitmproxy" @@ -91,7 +92,7 @@ class ProxyConfig: self.body_size_limit = body_size_limit self.mode = mode if upstream_server: - self.upstream_server = ServerSpec(upstream_server[0], Address.wrap(upstream_server[1])) + self.upstream_server = ServerSpec(upstream_server[0], tcp.Address.wrap(upstream_server[1])) self.upstream_auth = upstream_auth else: self.upstream_server = None @@ -111,9 +112,9 @@ class ProxyConfig: self.certstore.add_cert_file(spec, cert) self.openssl_method_client, self.openssl_options_client = \ - sslversion_choices[ssl_version_client] + tcp.sslversion_choices[ssl_version_client] self.openssl_method_server, self.openssl_options_server = \ - sslversion_choices[ssl_version_server] + tcp.sslversion_choices[ssl_version_server] if ssl_verify_upstream_cert: self.openssl_verification_mode_server = SSL.VERIFY_PEER diff --git a/mitmproxy/proxy/modes/__init__.py b/mitmproxy/proxy/modes/__init__.py index f014ed98..fa62570c 100644 --- a/mitmproxy/proxy/modes/__init__.py +++ b/mitmproxy/proxy/modes/__init__.py @@ -1,4 +1,5 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + from .http_proxy import HttpProxy, HttpUpstreamProxy from .reverse_proxy import ReverseProxy from .socks_proxy import Socks5Proxy diff --git a/mitmproxy/proxy/modes/http_proxy.py b/mitmproxy/proxy/modes/http_proxy.py index e19062b9..bc64ccd2 100644 --- a/mitmproxy/proxy/modes/http_proxy.py +++ b/mitmproxy/proxy/modes/http_proxy.py @@ -1,9 +1,9 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -from ...protocol import Layer, ServerConnectionMixin +from mitmproxy import protocol -class HttpProxy(Layer, ServerConnectionMixin): +class HttpProxy(protocol.Layer, protocol.ServerConnectionMixin): def __call__(self): layer = self.ctx.next_layer(self) @@ -14,7 +14,7 @@ class HttpProxy(Layer, ServerConnectionMixin): self.disconnect() -class HttpUpstreamProxy(Layer, ServerConnectionMixin): +class HttpUpstreamProxy(protocol.Layer, protocol.ServerConnectionMixin): def __init__(self, ctx, server_address): super(HttpUpstreamProxy, self).__init__(ctx, server_address=server_address) diff --git a/mitmproxy/proxy/modes/reverse_proxy.py b/mitmproxy/proxy/modes/reverse_proxy.py index c8e80a10..3739ac0e 100644 --- a/mitmproxy/proxy/modes/reverse_proxy.py +++ b/mitmproxy/proxy/modes/reverse_proxy.py @@ -1,9 +1,9 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -from ...protocol import Layer, ServerConnectionMixin +from mitmproxy import protocol -class ReverseProxy(Layer, ServerConnectionMixin): +class ReverseProxy(protocol.Layer, protocol.ServerConnectionMixin): def __init__(self, ctx, server_address, server_tls): super(ReverseProxy, self).__init__(ctx, server_address=server_address) diff --git a/mitmproxy/proxy/modes/socks_proxy.py b/mitmproxy/proxy/modes/socks_proxy.py index e2ce44ae..19437835 100644 --- a/mitmproxy/proxy/modes/socks_proxy.py +++ b/mitmproxy/proxy/modes/socks_proxy.py @@ -1,13 +1,13 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -from netlib import socks, tcp -from netlib.exceptions import TcpException +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import protocol +from netlib import socks +from netlib import tcp -from ...exceptions import Socks5ProtocolException -from ...protocol import Layer, ServerConnectionMixin - -class Socks5Proxy(Layer, ServerConnectionMixin): +class Socks5Proxy(protocol.Layer, protocol.ServerConnectionMixin): def __init__(self, ctx): super(Socks5Proxy, self).__init__(ctx) @@ -51,8 +51,8 @@ class Socks5Proxy(Layer, ServerConnectionMixin): connect_reply.to_file(self.client_conn.wfile) self.client_conn.wfile.flush() - except (socks.SocksError, TcpException) as e: - raise Socks5ProtocolException("SOCKS5 mode failure: %s" % repr(e)) + except (socks.SocksError, netlib.exceptions.TcpException) as e: + raise exceptions.Socks5ProtocolException("SOCKS5 mode failure: %s" % repr(e)) # https://github.com/mitmproxy/mitmproxy/issues/839 address_bytes = (connect_request.addr.host.encode("idna"), connect_request.addr.port) diff --git a/mitmproxy/proxy/modes/transparent_proxy.py b/mitmproxy/proxy/modes/transparent_proxy.py index 3fdda656..c7df7900 100644 --- a/mitmproxy/proxy/modes/transparent_proxy.py +++ b/mitmproxy/proxy/modes/transparent_proxy.py @@ -1,11 +1,11 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -from ... import platform -from ...exceptions import ProtocolException -from ...protocol import Layer, ServerConnectionMixin +from mitmproxy import exceptions +from mitmproxy import platform +from mitmproxy import protocol -class TransparentProxy(Layer, ServerConnectionMixin): +class TransparentProxy(protocol.Layer, protocol.ServerConnectionMixin): def __init__(self, ctx): super(TransparentProxy, self).__init__(ctx) @@ -15,7 +15,7 @@ class TransparentProxy(Layer, ServerConnectionMixin): try: self.server_conn.address = self.resolver.original_addr(self.client_conn.connection) except Exception as e: - raise ProtocolException("Transparent mode failure: %s" % repr(e)) + raise exceptions.ProtocolException("Transparent mode failure: %s" % repr(e)) layer = self.ctx.next_layer(self) try: diff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py index 9b4e2963..57183c7e 100644 --- a/mitmproxy/proxy/root_context.py +++ b/mitmproxy/proxy/root_context.py @@ -1,15 +1,13 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import sys import six -from mitmproxy.exceptions import ProtocolException, TlsProtocolException -from netlib.exceptions import TcpException -from ..protocol import ( - RawTCPLayer, TlsLayer, Http1Layer, Http2Layer, is_tls_record_magic, ServerConnectionMixin, - UpstreamConnectLayer, TlsClientHello -) -from .modes import HttpProxy, HttpUpstreamProxy, ReverseProxy +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import protocol +from mitmproxy.proxy import modes class RootContext(object): @@ -50,53 +48,53 @@ class RootContext(object): def _next_layer(self, top_layer): try: d = top_layer.client_conn.rfile.peek(3) - except TcpException as e: - six.reraise(ProtocolException, ProtocolException(str(e)), sys.exc_info()[2]) - client_tls = is_tls_record_magic(d) + except netlib.exceptions.TcpException as e: + six.reraise(exceptions.ProtocolException, exceptions.ProtocolException(str(e)), sys.exc_info()[2]) + client_tls = protocol.is_tls_record_magic(d) # 1. check for --ignore if self.config.check_ignore: ignore = self.config.check_ignore(top_layer.server_conn.address) if not ignore and client_tls: try: - client_hello = TlsClientHello.from_client_conn(self.client_conn) - except TlsProtocolException as e: + client_hello = protocol.TlsClientHello.from_client_conn(self.client_conn) + except exceptions.TlsProtocolException as e: self.log("Cannot parse Client Hello: %s" % repr(e), "error") else: ignore = self.config.check_ignore((client_hello.sni, 443)) if ignore: - return RawTCPLayer(top_layer, ignore=True) + return protocol.RawTCPLayer(top_layer, ignore=True) # 2. Always insert a TLS layer, even if there's neither client nor server tls. # An inline script may upgrade from http to https, # in which case we need some form of TLS layer. - if isinstance(top_layer, ReverseProxy): - return TlsLayer(top_layer, client_tls, top_layer.server_tls) - if isinstance(top_layer, ServerConnectionMixin) or isinstance(top_layer, UpstreamConnectLayer): - return TlsLayer(top_layer, client_tls, client_tls) + if isinstance(top_layer, modes.ReverseProxy): + return protocol.TlsLayer(top_layer, client_tls, top_layer.server_tls) + if isinstance(top_layer, protocol.ServerConnectionMixin) or isinstance(top_layer, protocol.UpstreamConnectLayer): + return protocol.TlsLayer(top_layer, client_tls, client_tls) # 3. In Http Proxy mode and Upstream Proxy mode, the next layer is fixed. - if isinstance(top_layer, TlsLayer): - if isinstance(top_layer.ctx, HttpProxy): - return Http1Layer(top_layer, "regular") - if isinstance(top_layer.ctx, HttpUpstreamProxy): - return Http1Layer(top_layer, "upstream") + if isinstance(top_layer, protocol.TlsLayer): + if isinstance(top_layer.ctx, modes.HttpProxy): + return protocol.Http1Layer(top_layer, "regular") + if isinstance(top_layer.ctx, modes.HttpUpstreamProxy): + return protocol.Http1Layer(top_layer, "upstream") # 4. Check for other TLS cases (e.g. after CONNECT). if client_tls: - return TlsLayer(top_layer, True, True) + return protocol.TlsLayer(top_layer, True, True) # 4. Check for --tcp if self.config.check_tcp(top_layer.server_conn.address): - return RawTCPLayer(top_layer) + return protocol.RawTCPLayer(top_layer) # 5. Check for TLS ALPN (HTTP1/HTTP2) - if isinstance(top_layer, TlsLayer): + if isinstance(top_layer, protocol.TlsLayer): alpn = top_layer.client_conn.get_alpn_proto_negotiated() if alpn == b'h2': - return Http2Layer(top_layer, 'transparent') + return protocol.Http2Layer(top_layer, 'transparent') if alpn == b'http/1.1': - return Http1Layer(top_layer, 'transparent') + return protocol.Http1Layer(top_layer, 'transparent') # 6. Check for raw tcp mode is_ascii = ( @@ -105,10 +103,10 @@ class RootContext(object): all(65 <= x <= 90 and 97 <= x <= 122 for x in six.iterbytes(d)) ) if self.config.rawtcp and not is_ascii: - return RawTCPLayer(top_layer) + return protocol.RawTCPLayer(top_layer) # 7. Assume HTTP1 by default - return Http1Layer(top_layer, 'transparent') + return protocol.Http1Layer(top_layer, 'transparent') def log(self, msg, level, subs=()): """ diff --git a/mitmproxy/proxy/server.py b/mitmproxy/proxy/server.py index 8483d3df..7e96911a 100644 --- a/mitmproxy/proxy/server.py +++ b/mitmproxy/proxy/server.py @@ -1,17 +1,18 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division -import traceback -import sys import socket +import sys +import traceback + import six +import netlib.exceptions +from mitmproxy import exceptions +from mitmproxy import models +from mitmproxy.proxy import modes +from mitmproxy.proxy import root_context from netlib import tcp -from netlib.exceptions import TcpException -from netlib.http.http1 import assemble_response -from ..exceptions import ProtocolException, ServerException, ClientHandshakeException, Kill -from ..models import ClientConnection, make_error_response -from .modes import HttpUpstreamProxy, HttpProxy, ReverseProxy, TransparentProxy, Socks5Proxy -from .root_context import RootContext, Log +from netlib.http import http1 class DummyServer: @@ -43,8 +44,8 @@ class ProxyServer(tcp.TCPServer): super(ProxyServer, self).__init__((config.host, config.port)) except socket.error as e: six.reraise( - ServerException, - ServerException('Error starting proxy server: ' + repr(e)), + exceptions.ServerException, + exceptions.ServerException('Error starting proxy server: ' + repr(e)), sys.exc_info()[2] ) self.channel = None @@ -67,7 +68,7 @@ class ConnectionHandler(object): def __init__(self, client_conn, client_address, config, channel): self.config = config """@type: mitmproxy.proxy.config.ProxyConfig""" - self.client_conn = ClientConnection( + self.client_conn = models.ClientConnection( client_conn, client_address, None) @@ -76,7 +77,7 @@ class ConnectionHandler(object): """@type: mitmproxy.controller.Channel""" def _create_root_layer(self): - root_context = RootContext( + root_ctx = root_context.RootContext( self.client_conn, self.config, self.channel @@ -84,25 +85,25 @@ class ConnectionHandler(object): mode = self.config.mode if mode == "upstream": - return HttpUpstreamProxy( - root_context, + return modes.HttpUpstreamProxy( + root_ctx, self.config.upstream_server.address ) elif mode == "transparent": - return TransparentProxy(root_context) + return modes.TransparentProxy(root_ctx) elif mode == "reverse": server_tls = self.config.upstream_server.scheme == "https" - return ReverseProxy( - root_context, + return modes.ReverseProxy( + root_ctx, self.config.upstream_server.address, server_tls ) elif mode == "socks5": - return Socks5Proxy(root_context) + return modes.Socks5Proxy(root_ctx) elif mode == "regular": - return HttpProxy(root_context) + return modes.HttpProxy(root_ctx) elif callable(mode): # pragma: no cover - return mode(root_context) + return mode(root_ctx) else: # pragma: no cover raise ValueError("Unknown proxy mode: %s" % mode) @@ -114,11 +115,11 @@ class ConnectionHandler(object): try: root_layer = self.channel.ask("clientconnect", root_layer) root_layer() - except Kill: + except exceptions.Kill: self.log("Connection killed", "info") - except ProtocolException as e: + except exceptions.ProtocolException as e: - if isinstance(e, ClientHandshakeException): + if isinstance(e, exceptions.ClientHandshakeException): self.log( "Client Handshake failed. " "The client may not trust the proxy's certificate for {}.".format(e.server), @@ -133,9 +134,9 @@ class ConnectionHandler(object): # we send an HTTP error response, which is both # understandable by HTTP clients and humans. try: - error_response = make_error_response(502, repr(e)) - self.client_conn.send(assemble_response(error_response)) - except TcpException: + error_response = models.make_error_response(502, repr(e)) + self.client_conn.send(http1.assemble_response(error_response)) + except netlib.exceptions.TcpException: pass except Exception: self.log(traceback.format_exc(), "error") @@ -149,4 +150,4 @@ class ConnectionHandler(object): def log(self, msg, level): msg = "{}: {}".format(repr(self.client_conn.address), msg) - self.channel.tell("log", Log(msg, level)) + self.channel.tell("log", root_context.Log(msg, level)) diff --git a/mitmproxy/script/__init__.py b/mitmproxy/script/__init__.py index 3ee19b04..d6bff4c7 100644 --- a/mitmproxy/script/__init__.py +++ b/mitmproxy/script/__init__.py @@ -1,8 +1,8 @@ +from . import reloader +from .concurrent import concurrent from .script import Script from .script_context import ScriptContext -from .concurrent import concurrent from ..exceptions import ScriptException -from . import reloader __all__ = [ "Script", diff --git a/mitmproxy/script/concurrent.py b/mitmproxy/script/concurrent.py index 2f25e78c..43d0d328 100644 --- a/mitmproxy/script/concurrent.py +++ b/mitmproxy/script/concurrent.py @@ -3,6 +3,7 @@ This module provides a @concurrent decorator primitive to offload computations from mitmproxy's main master thread. """ from __future__ import absolute_import, print_function, division + import threading diff --git a/mitmproxy/script/reloader.py b/mitmproxy/script/reloader.py index 99ce7f60..f5470bbf 100644 --- a/mitmproxy/script/reloader.py +++ b/mitmproxy/script/reloader.py @@ -1,6 +1,10 @@ +from __future__ import absolute_import, print_function, division + import os import sys + from watchdog.events import RegexMatchingEventHandler + if sys.platform == 'darwin': # pragma: no cover from watchdog.observers.polling import PollingObserver as Observer else: diff --git a/mitmproxy/script/script.py b/mitmproxy/script/script.py index 9bf05f27..70f74817 100644 --- a/mitmproxy/script/script.py +++ b/mitmproxy/script/script.py @@ -4,13 +4,15 @@ Script objects know nothing about mitmproxy or mitmproxy's API - this knowledge by the mitmproxy-specific ScriptContext. """ # Do not import __future__ here, this would apply transitively to the inline scripts. +from __future__ import absolute_import, print_function, division + import os import shlex import sys import six -from ..exceptions import ScriptException +from mitmproxy import exceptions class Script(object): @@ -41,7 +43,7 @@ class Script(object): @staticmethod def parse_command(command): if not command or not command.strip(): - raise ScriptException("Empty script command.") + raise exceptions.ScriptException("Empty script command.") # Windows: escape all backslashes in the path. if os.name == "nt": # pragma: no cover backslashes = shlex.split(command, posix=False)[0].count("\\") @@ -49,13 +51,13 @@ class Script(object): args = shlex.split(command) # pragma: no cover args[0] = os.path.expanduser(args[0]) if not os.path.exists(args[0]): - raise ScriptException( + raise exceptions.ScriptException( ("Script file not found: %s.\r\n" "If your script path contains spaces, " "make sure to wrap it in additional quotes, e.g. -s \"'./foo bar/baz.py' --args\".") % args[0]) elif os.path.isdir(args[0]): - raise ScriptException("Not a file: %s" % args[0]) + raise exceptions.ScriptException("Not a file: %s" % args[0]) return args def load(self): @@ -69,7 +71,7 @@ class Script(object): ScriptException on failure """ if self.ns is not None: - raise ScriptException("Script is already loaded") + raise exceptions.ScriptException("Script is already loaded") script_dir = os.path.dirname(os.path.abspath(self.args[0])) self.ns = {'__file__': os.path.abspath(self.args[0])} sys.path.append(script_dir) @@ -80,8 +82,8 @@ class Script(object): exec(code, self.ns, self.ns) except Exception: six.reraise( - ScriptException, - ScriptException.from_exception_context(), + exceptions.ScriptException, + exceptions.ScriptException.from_exception_context(), sys.exc_info()[2] ) finally: @@ -107,15 +109,15 @@ class Script(object): ScriptException if there was an exception. """ if self.ns is None: - raise ScriptException("Script not loaded.") + raise exceptions.ScriptException("Script not loaded.") f = self.ns.get(name) if f: try: return f(self.ctx, *args, **kwargs) except Exception: six.reraise( - ScriptException, - ScriptException.from_exception_context(), + exceptions.ScriptException, + exceptions.ScriptException.from_exception_context(), sys.exc_info()[2] ) else: diff --git a/mitmproxy/script/script_context.py b/mitmproxy/script/script_context.py index cd5d4b61..44e2736b 100644 --- a/mitmproxy/script/script_context.py +++ b/mitmproxy/script/script_context.py @@ -2,7 +2,8 @@ The mitmproxy script context provides an API to inline scripts. """ from __future__ import absolute_import, print_function, division -from .. import contentviews + +from mitmproxy import contentviews class ScriptContext(object): diff --git a/mitmproxy/stateobject.py b/mitmproxy/stateobject.py index eb57fa00..6283d845 100644 --- a/mitmproxy/stateobject.py +++ b/mitmproxy/stateobject.py @@ -1,7 +1,8 @@ -from __future__ import absolute_import +from __future__ import absolute_import, print_function, division import six -from typing import List, Any +from typing import Any +from typing import List import netlib.basetypes diff --git a/mitmproxy/tnetstring.py b/mitmproxy/tnetstring.py index acf563ac..6b1c117a 100644 --- a/mitmproxy/tnetstring.py +++ b/mitmproxy/tnetstring.py @@ -67,9 +67,10 @@ like so:: u'\u03b1' """ -import six from collections import deque +import six + __ver_major__ = 0 __ver_minor__ = 2 __ver_patch__ = 0 diff --git a/mitmproxy/utils.py b/mitmproxy/utils.py index 05342500..672805d0 100644 --- a/mitmproxy/utils.py +++ b/mitmproxy/utils.py @@ -1,7 +1,8 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division + import datetime -import time import json +import time import netlib.utils diff --git a/mitmproxy/version.py b/mitmproxy/version.py index 02b0d900..0ebb0829 100644 --- a/mitmproxy/version.py +++ b/mitmproxy/version.py @@ -1,4 +1,4 @@ -from __future__ import (absolute_import, print_function, division) +from __future__ import absolute_import, print_function, division from netlib.version import VERSION, IVERSION diff --git a/mitmproxy/web/__init__.py b/mitmproxy/web/__init__.py index 79c81687..80a65886 100644 --- a/mitmproxy/web/__init__.py +++ b/mitmproxy/web/__init__.py @@ -1,14 +1,16 @@ -from __future__ import absolute_import, print_function +from __future__ import absolute_import, print_function, division + import collections -import tornado.ioloop -import tornado.httpserver import sys -from netlib.http import authentication +import tornado.httpserver +import tornado.ioloop -from .. import flow, controller -from ..exceptions import FlowReadException -from . import app +from mitmproxy import controller +from mitmproxy import exceptions +from mitmproxy import flow +from mitmproxy.web import app +from netlib.http import authentication class Stop(Exception): @@ -156,7 +158,7 @@ class WebMaster(flow.FlowMaster): if options.rfile: try: self.load_flows_file(options.rfile) - except FlowReadException as v: + except exceptions.FlowReadException as v: self.add_event( "Could not read flow file: %s" % v, "error" diff --git a/mitmproxy/web/app.py b/mitmproxy/web/app.py index e25c9086..43b2bad1 100644 --- a/mitmproxy/web/app.py +++ b/mitmproxy/web/app.py @@ -1,14 +1,16 @@ +from __future__ import absolute_import, print_function, division + +import base64 +import json +import logging import os.path import re import six -import tornado.web import tornado.websocket -import logging -import json -import base64 -from .. import version, filt +from mitmproxy import filt +from mitmproxy import version def _strip_content(flow_state): diff --git a/netlib/http/http2/__init__.py b/netlib/http/http2/__init__.py index 7043d36f..633e6a20 100644 --- a/netlib/http/http2/__init__.py +++ b/netlib/http/http2/__init__.py @@ -1,6 +1,8 @@ from __future__ import absolute_import, print_function, division from .connections import HTTP2Protocol +from netlib.http.http2 import framereader __all__ = [ - "HTTP2Protocol" + "HTTP2Protocol", + "framereader", ] |