Move all tools into mitmproxy.tools, move models/* to top level

The primary motivation here (and for all the other moving around) is to present
a clean "front of house" to library users, and to migrate primary objects to
the top of the module hierarchy.
This commit is contained in:
Aldo Cortesi 2016-10-19 15:25:39 +13:00
parent 5a68d21e8c
commit 24cf8da27e
95 changed files with 381 additions and 378 deletions

View File

@ -5,11 +5,11 @@ API
===
- Errors
- `mitmproxy.models.flow.Error <#mitmproxy.models.flow.Error>`_
- `mitmproxy.flow.Error <#mitmproxy.flow.Error>`_
- HTTP
- `mitmproxy.models.http.HTTPRequest <#mitmproxy.models.http.HTTPRequest>`_
- `mitmproxy.models.http.HTTPResponse <#mitmproxy.models.http.HTTPResponse>`_
- `mitmproxy.models.http.HTTPFlow <#mitmproxy.models.http.HTTPFlow>`_
- `mitmproxy.http.HTTPRequest <#mitmproxy.http.HTTPRequest>`_
- `mitmproxy.http.HTTPResponse <#mitmproxy.http.HTTPResponse>`_
- `mitmproxy.http.HTTPFlow <#mitmproxy.http.HTTPFlow>`_
- Logging
- `mitmproxy.log.Log <#mitmproxy.controller.Log>`_
- `mitmproxy.log.LogEntry <#mitmproxy.controller.LogEntry>`_
@ -18,19 +18,19 @@ API
Errors
------
.. autoclass:: mitmproxy.models.flow.Error
.. autoclass:: mitmproxy.flow.Error
:inherited-members:
HTTP
----
.. autoclass:: mitmproxy.models.http.HTTPRequest
.. autoclass:: mitmproxy.http.HTTPRequest
:inherited-members:
.. autoclass:: mitmproxy.models.http.HTTPResponse
.. autoclass:: mitmproxy.http.HTTPResponse
:inherited-members:
.. autoclass:: mitmproxy.models.http.HTTPFlow
.. autoclass:: mitmproxy.http.HTTPFlow
:inherited-members:
Logging

View File

@ -1,6 +1,6 @@
import random
import sys
from mimtproxy import io
from mitmproxy import io
class Writer:

View File

@ -1,7 +1,7 @@
"""
This example shows two ways to redirect flows to other destinations.
"""
from mitmproxy.models import HTTPResponse
from mitmproxy import http
def request(flow):
@ -11,7 +11,7 @@ def request(flow):
# Method 1: Answer with a locally generated response
if flow.request.pretty_host.endswith("example.com"):
flow.response = HTTPResponse.make(200, b"Hello World", {"Content-Type": "text/html"})
flow.response = http.HTTPResponse.make(200, b"Hello World", {"Content-Type": "text/html"})
# Method 2: Redirect the request to a different server
if flow.request.pretty_host.endswith("example.org"):

View File

@ -3,7 +3,6 @@ from mitmproxy import ctx
from mitmproxy import io
class ClientPlayback:
def __init__(self):
self.flows = None

View File

@ -8,7 +8,7 @@ from mitmproxy import io
class FileStreamer:
def __init__(self):
self.stream = None
self.active_flows = set() # type: Set[models.Flow]
self.active_flows = set() # type: Set[flow.Flow]
def start_stream_to_path(self, path, mode, flt):
path = os.path.expanduser(path)

View File

@ -3,12 +3,12 @@ from abc import abstractmethod, ABCMeta
from typing import List # noqa
from mitmproxy import flowfilter
from mitmproxy import models # noqa
from mitmproxy import flow # noqa
class FlowList(metaclass=ABCMeta):
def __init__(self):
self._list = [] # type: List[models.Flow]
self._list = [] # type: List[flow.Flow]
def __iter__(self):
return iter(self._list)

View File

@ -1,4 +0,0 @@
from mitmproxy.console import master
__all__ = ["master"]

View File

@ -1,5 +1,6 @@
from mitmproxy import controller
from mitmproxy import models
from mitmproxy import http
from mitmproxy import tcp
Events = frozenset([
"clientconnect",
@ -34,7 +35,7 @@ Events = frozenset([
def event_sequence(f):
if isinstance(f, models.HTTPFlow):
if isinstance(f, http.HTTPFlow):
if f.request:
yield "requestheaders", f
yield "request", f
@ -43,7 +44,7 @@ def event_sequence(f):
yield "response", f
if f.error:
yield "error", f
elif isinstance(f, models.TCPFlow):
elif isinstance(f, tcp.TCPFlow):
messages = f.messages
f.messages = []
f.reply = controller.DummyReply()

View File

@ -3,8 +3,7 @@ import copy
import uuid
from mitmproxy import stateobject
from mitmproxy.models.connections import ClientConnection
from mitmproxy.models.connections import ServerConnection
from mitmproxy import connections
from netlib import version
from typing import Optional # noqa
@ -68,8 +67,8 @@ class Flow(stateobject.StateObject):
def __init__(
self,
type: str,
client_conn: ClientConnection,
server_conn: ServerConnection,
client_conn: connections.ClientConnection,
server_conn: connections.ServerConnection,
live=None
):
self.type = type
@ -87,8 +86,8 @@ class Flow(stateobject.StateObject):
_stateobject_attributes = dict(
id=str,
error=Error,
client_conn=ClientConnection,
server_conn=ServerConnection,
client_conn=connections.ClientConnection,
server_conn=connections.ServerConnection,
type=str,
intercepted=bool,
marked=bool,

View File

@ -36,9 +36,9 @@ import re
import sys
import functools
from mitmproxy.models.http import HTTPFlow
from mitmproxy.models.tcp import TCPFlow
from mitmproxy.models.flow import Flow
from mitmproxy import http
from mitmproxy import tcp
from mitmproxy import flow
from netlib import strutils
@ -94,7 +94,7 @@ class FHTTP(_Action):
code = "http"
help = "Match HTTP flows"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return True
@ -103,7 +103,7 @@ class FTCP(_Action):
code = "tcp"
help = "Match TCP flows"
@only(TCPFlow)
@only(tcp.TCPFlow)
def __call__(self, f):
return True
@ -112,7 +112,7 @@ class FReq(_Action):
code = "q"
help = "Match request with no response"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if not f.response:
return True
@ -122,7 +122,7 @@ class FResp(_Action):
code = "s"
help = "Match response"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return bool(f.response)
@ -162,7 +162,7 @@ class FAsset(_Action):
]
ASSET_TYPES = [re.compile(x) for x in ASSET_TYPES]
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.response:
for i in self.ASSET_TYPES:
@ -175,7 +175,7 @@ class FContentType(_Rex):
code = "t"
help = "Content-type header"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if _check_content_type(self.re, f.request):
return True
@ -188,7 +188,7 @@ class FContentTypeRequest(_Rex):
code = "tq"
help = "Request Content-Type header"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return _check_content_type(self.re, f.request)
@ -197,7 +197,7 @@ class FContentTypeResponse(_Rex):
code = "ts"
help = "Response Content-Type header"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.response:
return _check_content_type(self.re, f.response)
@ -209,7 +209,7 @@ class FHead(_Rex):
help = "Header"
flags = re.MULTILINE
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.request and self.re.search(bytes(f.request.headers)):
return True
@ -223,7 +223,7 @@ class FHeadRequest(_Rex):
help = "Request header"
flags = re.MULTILINE
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.request and self.re.search(bytes(f.request.headers)):
return True
@ -234,7 +234,7 @@ class FHeadResponse(_Rex):
help = "Response header"
flags = re.MULTILINE
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.response and self.re.search(bytes(f.response.headers)):
return True
@ -245,16 +245,16 @@ class FBod(_Rex):
help = "Body"
flags = re.DOTALL
@only(HTTPFlow, TCPFlow)
@only(http.HTTPFlow, tcp.TCPFlow)
def __call__(self, f):
if isinstance(f, HTTPFlow):
if isinstance(f, http.HTTPFlow):
if f.request and f.request.raw_content:
if self.re.search(f.request.get_content(strict=False)):
return True
if f.response and f.response.raw_content:
if self.re.search(f.response.get_content(strict=False)):
return True
elif isinstance(f, TCPFlow):
elif isinstance(f, tcp.TCPFlow):
for msg in f.messages:
if self.re.search(msg.content):
return True
@ -266,13 +266,13 @@ class FBodRequest(_Rex):
help = "Request body"
flags = re.DOTALL
@only(HTTPFlow, TCPFlow)
@only(http.HTTPFlow, tcp.TCPFlow)
def __call__(self, f):
if isinstance(f, HTTPFlow):
if isinstance(f, http.HTTPFlow):
if f.request and f.request.raw_content:
if self.re.search(f.request.get_content(strict=False)):
return True
elif isinstance(f, TCPFlow):
elif isinstance(f, tcp.TCPFlow):
for msg in f.messages:
if msg.from_client and self.re.search(msg.content):
return True
@ -283,13 +283,13 @@ class FBodResponse(_Rex):
help = "Response body"
flags = re.DOTALL
@only(HTTPFlow, TCPFlow)
@only(http.HTTPFlow, tcp.TCPFlow)
def __call__(self, f):
if isinstance(f, HTTPFlow):
if isinstance(f, http.HTTPFlow):
if f.response and f.response.raw_content:
if self.re.search(f.response.get_content(strict=False)):
return True
elif isinstance(f, TCPFlow):
elif isinstance(f, tcp.TCPFlow):
for msg in f.messages:
if not msg.from_client and self.re.search(msg.content):
return True
@ -300,7 +300,7 @@ class FMethod(_Rex):
help = "Method"
flags = re.IGNORECASE
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return bool(self.re.search(f.request.data.method))
@ -310,7 +310,7 @@ class FDomain(_Rex):
help = "Domain"
flags = re.IGNORECASE
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return bool(self.re.search(f.request.data.host))
@ -327,7 +327,7 @@ class FUrl(_Rex):
toks = toks[1:]
return klass(*toks)
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
return self.re.search(f.request.url)
@ -360,7 +360,7 @@ class FCode(_Int):
code = "c"
help = "HTTP response code"
@only(HTTPFlow)
@only(http.HTTPFlow)
def __call__(self, f):
if f.response and f.response.status_code == self.num:
return True
@ -485,7 +485,7 @@ def _make():
bnf = _make()
TFilter = Callable[[Flow], bool]
TFilter = Callable[[flow.Flow], bool]
def parse(s: str) -> TFilter:

View File

@ -1,6 +1,6 @@
import cgi
from mitmproxy.models import flow
from mitmproxy import flow
from netlib import http
from netlib import version
from netlib import tcp

View File

@ -2,11 +2,18 @@ import os
from mitmproxy import exceptions
from mitmproxy import flowfilter
from mitmproxy import models
from mitmproxy import http
from mitmproxy import tcp
from mitmproxy.contrib import tnetstring
from mitmproxy import io_compat
FLOW_TYPES = dict(
http=http.HTTPFlow,
tcp=tcp.TCPFlow,
)
class FlowWriter:
def __init__(self, fo):
self.fo = fo
@ -31,9 +38,9 @@ class FlowReader:
data = io_compat.migrate_flow(data)
except ValueError as e:
raise exceptions.FlowReadException(str(e))
if data["type"] not in models.FLOW_TYPES:
if data["type"] not in FLOW_TYPES:
raise exceptions.FlowReadException("Unknown flow type: {}".format(data["type"]))
yield models.FLOW_TYPES[data["type"]].from_state(data)
yield FLOW_TYPES[data["type"]].from_state(data)
except ValueError as e:
if str(e) == "not a tnetstring: empty file":
return # Error is due to EOF

View File

@ -9,12 +9,13 @@ from mitmproxy import options
from mitmproxy import controller
from mitmproxy import events
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import connections
from mitmproxy import http
from mitmproxy import log
from mitmproxy import io
from mitmproxy.protocol import http_replay
from netlib import basethread
from netlib import http
import netlib.http
from . import ctx as mitmproxy_ctx
@ -117,13 +118,13 @@ class Master:
"""
this method creates a new artificial and minimalist request also adds it to flowlist
"""
c = models.ClientConnection.make_dummy(("", 0))
s = models.ServerConnection.make_dummy((host, port))
c = connections.ClientConnection.make_dummy(("", 0))
s = connections.ServerConnection.make_dummy((host, port))
f = models.HTTPFlow(c, s)
headers = http.Headers()
f = http.HTTPFlow(c, s)
headers = netlib.http.Headers()
req = models.HTTPRequest(
req = http.HTTPRequest(
"absolute",
method,
scheme,
@ -142,7 +143,7 @@ class Master:
"""
Loads a flow
"""
if isinstance(f, models.HTTPFlow):
if isinstance(f, http.HTTPFlow):
if self.server and self.options.mode == "reverse":
f.request.host = self.server.config.upstream_server.address.host
f.request.port = self.server.config.upstream_server.address.port

View File

@ -1,23 +0,0 @@
from netlib.http import decoded
from .connections import ClientConnection, ServerConnection
from .flow import Flow, Error
from .http import (
HTTPFlow, HTTPRequest, HTTPResponse,
make_error_response, make_connect_request, make_connect_response, expect_continue_response
)
from .tcp import TCPFlow
FLOW_TYPES = dict(
http=HTTPFlow,
tcp=TCPFlow,
)
__all__ = [
"HTTPFlow", "HTTPRequest", "HTTPResponse", "decoded",
"make_error_response", "make_connect_request",
"make_connect_response", "expect_continue_response",
"ClientConnection", "ServerConnection",
"Flow", "Error",
"TCPFlow",
"FLOW_TYPES",
]

View File

@ -1,6 +1,6 @@
import netlib.exceptions
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import connections
class _LayerCodeCompletion:
@ -16,9 +16,9 @@ class _LayerCodeCompletion:
self.config = None
"""@type: mitmproxy.proxy.ProxyConfig"""
self.client_conn = None
"""@type: mitmproxy.models.ClientConnection"""
"""@type: mitmproxy.connections.ClientConnection"""
self.server_conn = None
"""@type: mitmproxy.models.ServerConnection"""
"""@type: mitmproxy.connections.ServerConnection"""
self.channel = None
"""@type: mitmproxy.controller.Channel"""
self.ctx = None
@ -111,10 +111,10 @@ class ServerConnectionMixin:
self.server_conn = None
if self.config.options.spoof_source_address:
self.server_conn = models.ServerConnection(
self.server_conn = connections.ServerConnection(
server_address, (self.ctx.client_conn.address.host, 0), True)
else:
self.server_conn = models.ServerConnection(
self.server_conn = connections.ServerConnection(
server_address, (self.config.options.listen_host, 0))
self.__check_self_connect()
@ -157,7 +157,7 @@ class ServerConnectionMixin:
self.server_conn.close()
self.channel.tell("serverdisconnect", self.server_conn)
self.server_conn = models.ServerConnection(
self.server_conn = connections.ServerConnection(
address,
(self.server_conn.source_address.host, 0),
self.config.options.spoof_source_address

View File

@ -3,10 +3,11 @@ import netlib.exceptions
import time
import traceback
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import http
from mitmproxy import flow
from mitmproxy.protocol import base
from mitmproxy.protocol import websockets as pwebsockets
from netlib import http
import netlib.http
from netlib import tcp
from netlib import websockets
@ -55,7 +56,7 @@ class _HttpTransmissionLayer(base.Layer):
def send_response_body(self, response, chunks):
raise NotImplementedError()
def check_close_connection(self, flow):
def check_close_connection(self, f):
raise NotImplementedError()
@ -140,9 +141,9 @@ class HttpLayer(base.Layer):
self.__initial_server_tls = self.server_tls
self.__initial_server_conn = self.server_conn
while True:
flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self)
f = http.HTTPFlow(self.client_conn, self.server_conn, live=self)
try:
request = self.get_request_from_client(flow)
request = self.get_request_from_client(f)
# Make sure that the incoming request matches our expectations
self.validate_request(request)
except netlib.exceptions.HttpReadDisconnect:
@ -165,7 +166,7 @@ class HttpLayer(base.Layer):
if not (self.http_authenticated or self.authenticate(request)):
return
flow.request = request
f.request = request
try:
# Regular Proxy Mode: Handle CONNECT
@ -176,74 +177,74 @@ class HttpLayer(base.Layer):
# HTTPS tasting means that ordinary errors like resolution and
# connection errors can happen here.
self.send_error_response(502, repr(e))
flow.error = models.Error(str(e))
self.channel.ask("error", flow)
f.error = flow.Error(str(e))
self.channel.ask("error", f)
return
# update host header in reverse proxy mode
if self.config.options.mode == "reverse":
flow.request.headers["Host"] = self.config.upstream_server.address.host
f.request.headers["Host"] = self.config.upstream_server.address.host
# set upstream auth
if self.mode == "upstream" and self.config.upstream_auth is not None:
flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth
self.process_request_hook(flow)
f.request.headers["Proxy-Authorization"] = self.config.upstream_auth
self.process_request_hook(f)
try:
if websockets.check_handshake(request.headers) and websockets.check_client_version(request.headers):
# We only support RFC6455 with WebSockets version 13
# allow inline scripts to manipulate the client handshake
self.channel.ask("websocket_handshake", flow)
self.channel.ask("websocket_handshake", f)
if not flow.response:
if not f.response:
self.establish_server_connection(
flow.request.host,
flow.request.port,
flow.request.scheme
f.request.host,
f.request.port,
f.request.scheme
)
self.get_response_from_server(flow)
self.get_response_from_server(f)
else:
# response was set by an inline script.
# we now need to emulate the responseheaders hook.
self.channel.ask("responseheaders", flow)
self.channel.ask("responseheaders", f)
self.log("response", "debug", [repr(flow.response)])
self.channel.ask("response", flow)
self.send_response_to_client(flow)
self.log("response", "debug", [repr(f.response)])
self.channel.ask("response", f)
self.send_response_to_client(f)
if self.check_close_connection(flow):
if self.check_close_connection(f):
return
# Handle 101 Switching Protocols
if flow.response.status_code == 101:
return self.handle_101_switching_protocols(flow)
if f.response.status_code == 101:
return self.handle_101_switching_protocols(f)
# Upstream Proxy Mode: Handle CONNECT
if flow.request.first_line_format == "authority" and flow.response.status_code == 200:
self.handle_upstream_mode_connect(flow.request.copy())
if f.request.first_line_format == "authority" and f.response.status_code == 200:
self.handle_upstream_mode_connect(f.request.copy())
return
except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e:
self.send_error_response(502, repr(e))
if not flow.response:
flow.error = models.Error(str(e))
self.channel.ask("error", flow)
if not f.response:
f.error = flow.Error(str(e))
self.channel.ask("error", f)
return
else:
raise exceptions.ProtocolException(
"Error in HTTP connection: %s" % repr(e)
)
finally:
if flow:
flow.live = False
if f:
f.live = False
def get_request_from_client(self, flow):
def get_request_from_client(self, f):
request = self.read_request()
flow.request = request
self.channel.ask("requestheaders", flow)
f.request = request
self.channel.ask("requestheaders", f)
if request.headers.get("expect", "").lower() == "100-continue":
# TODO: We may have to use send_response_headers for HTTP2 here.
self.send_response(models.expect_continue_response)
self.send_response(http.expect_continue_response)
request.headers.pop("expect")
request.body = b"".join(self.read_request_body(request))
request.timestamp_end = time.time()
@ -251,7 +252,7 @@ class HttpLayer(base.Layer):
def send_error_response(self, code, message, headers=None):
try:
response = models.make_error_response(code, message, headers)
response = http.make_error_response(code, message, headers)
self.send_response(response)
except (netlib.exceptions.NetlibException, h2.exceptions.H2Error, exceptions.Http2ProtocolException):
self.log(traceback.format_exc(), "debug")
@ -265,7 +266,7 @@ class HttpLayer(base.Layer):
def handle_regular_mode_connect(self, request):
self.http_authenticated = True
self.set_server((request.host, request.port))
self.send_response(models.make_connect_response(request.data.http_version))
self.send_response(http.make_connect_response(request.data.http_version))
layer = self.ctx.next_layer(self)
layer()
@ -273,29 +274,29 @@ class HttpLayer(base.Layer):
layer = UpstreamConnectLayer(self, connect_request)
layer()
def send_response_to_client(self, flow):
if not flow.response.stream:
def send_response_to_client(self, f):
if not f.response.stream:
# no streaming:
# we already received the full response from the server and can
# send it to the client straight away.
self.send_response(flow.response)
self.send_response(f.response)
else:
# streaming:
# First send the headers and then transfer the response incrementally
self.send_response_headers(flow.response)
self.send_response_headers(f.response)
chunks = self.read_response_body(
flow.request,
flow.response
f.request,
f.response
)
if callable(flow.response.stream):
chunks = flow.response.stream(chunks)
self.send_response_body(flow.response, chunks)
flow.response.timestamp_end = time.time()
if callable(f.response.stream):
chunks = f.response.stream(chunks)
self.send_response_body(f.response, chunks)
f.response.timestamp_end = time.time()
def get_response_from_server(self, flow):
def get_response_from_server(self, f):
def get_response():
self.send_request(flow.request)
flow.response = self.read_response_headers()
self.send_request(f.request)
f.response = self.read_response_headers()
try:
get_response()
@ -325,23 +326,23 @@ class HttpLayer(base.Layer):
get_response()
# call the appropriate script hook - this is an opportunity for an
# inline script to set flow.stream = True
self.channel.ask("responseheaders", flow)
# inline script to set f.stream = True
self.channel.ask("responseheaders", f)
if flow.response.stream:
flow.response.data.content = None
if f.response.stream:
f.response.data.content = None
else:
flow.response.data.content = b"".join(self.read_response_body(
flow.request,
flow.response
f.response.data.content = b"".join(self.read_response_body(
f.request,
f.response
))
flow.response.timestamp_end = time.time()
f.response.timestamp_end = time.time()
# no further manipulation of self.server_conn beyond this point
# we can safely set it as the final attribute value here.
flow.server_conn = self.server_conn
f.server_conn = self.server_conn
def process_request_hook(self, flow):
def process_request_hook(self, f):
# Determine .scheme, .host and .port attributes for inline scripts.
# For absolute-form requests, they are directly given in the request.
# For authority-form requests, we only need to determine the request scheme.
@ -353,13 +354,13 @@ class HttpLayer(base.Layer):
pass
else:
# Setting request.host also updates the host header, which we want to preserve
host_header = flow.request.headers.get("host", None)
flow.request.host = self.__initial_server_conn.address.host
flow.request.port = self.__initial_server_conn.address.port
host_header = f.request.headers.get("host", None)
f.request.host = self.__initial_server_conn.address.host
f.request.port = self.__initial_server_conn.address.port
if host_header:
flow.request.headers["host"] = host_header
flow.request.scheme = "https" if self.__initial_server_tls else "http"
self.channel.ask("request", flow)
f.request.headers["host"] = host_header
f.request.scheme = "https" if self.__initial_server_tls else "http"
self.channel.ask("request", f)
def establish_server_connection(self, host, port, scheme):
address = tcp.Address((host, port))
@ -419,29 +420,29 @@ class HttpLayer(base.Layer):
self.config.authenticator.clean(request.headers)
else:
if self.mode == "transparent":
self.send_response(models.make_error_response(
self.send_response(http.make_error_response(
401,
"Authentication Required",
http.Headers(**self.config.authenticator.auth_challenge_headers())
netlib.http.Headers(**self.config.authenticator.auth_challenge_headers())
))
else:
self.send_response(models.make_error_response(
self.send_response(http.make_error_response(
407,
"Proxy Authentication Required",
http.Headers(**self.config.authenticator.auth_challenge_headers())
netlib.http.Headers(**self.config.authenticator.auth_challenge_headers())
))
return False
return True
def handle_101_switching_protocols(self, flow):
def handle_101_switching_protocols(self, f):
"""
Handle a successful HTTP 101 Switching Protocols Response, received after e.g. a WebSocket upgrade request.
"""
# Check for WebSockets handshake
is_websockets = (
flow and
websockets.check_handshake(flow.request.headers) and
websockets.check_handshake(flow.response.headers)
f and
websockets.check_handshake(f.request.headers) and
websockets.check_handshake(f.response.headers)
)
if is_websockets and not self.config.options.websockets:
self.log(
@ -450,7 +451,7 @@ class HttpLayer(base.Layer):
)
if is_websockets and self.config.options.websockets:
layer = pwebsockets.WebSocketsLayer(self, flow)
layer = pwebsockets.WebSocketsLayer(self, f)
else:
layer = self.ctx.next_layer(self)

View File

@ -1,16 +1,16 @@
from mitmproxy import models
from mitmproxy.protocol import http
from mitmproxy import http
from mitmproxy.protocol import http as httpbase
from netlib.http import http1
class Http1Layer(http._HttpTransmissionLayer):
class Http1Layer(httpbase._HttpTransmissionLayer):
def __init__(self, ctx, mode):
super().__init__(ctx)
self.mode = mode
def read_request_headers(self):
return models.HTTPRequest.wrap(
return http.HTTPRequest.wrap(
http1.read_request_head(self.client_conn.rfile)
)
@ -28,7 +28,7 @@ class Http1Layer(http._HttpTransmissionLayer):
def read_response_headers(self):
resp = http1.read_response_head(self.server_conn.rfile)
return models.HTTPResponse.wrap(resp)
return http.HTTPResponse.wrap(resp)
def read_response_body(self, request, response):
expected_size = http1.expected_http_body_size(request, response)
@ -68,5 +68,5 @@ class Http1Layer(http._HttpTransmissionLayer):
return close_connection
def __call__(self):
layer = http.HttpLayer(self, self.mode)
layer = httpbase.HttpLayer(self, self.mode)
layer()

View File

@ -10,9 +10,9 @@ import queue
import netlib.exceptions
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import http
from mitmproxy.protocol import base
from mitmproxy.protocol import http
from mitmproxy.protocol import http as httpbase
import netlib.http
from netlib import tcp
from netlib import basethread
@ -358,7 +358,7 @@ def detect_zombie_stream(func):
return wrapper
class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread):
class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThread):
def __init__(self, ctx, h2_connection, stream_id, request_headers):
super().__init__(
@ -451,7 +451,7 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread)
self.request_arrived.wait()
self.raise_zombie()
first_line_format, method, scheme, host, port, path = http2.parse_headers(self.request_headers)
return models.HTTPRequest(
return http.HTTPRequest(
first_line_format,
method,
scheme,
@ -547,7 +547,7 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread)
headers = self.response_headers.copy()
headers.pop(":status", None)
return models.HTTPResponse(
return http.HTTPResponse(
http_version=b"HTTP/2.0",
status_code=status_code,
reason=b'',
@ -597,7 +597,7 @@ class Http2SingleStreamLayer(http._HttpTransmissionLayer, basethread.BaseThread)
raise EnvironmentError('Http2SingleStreamLayer must be run as thread')
def run(self):
layer = http.HttpLayer(self, self.mode)
layer = httpbase.HttpLayer(self, self.mode)
try:
layer()

View File

@ -1,9 +1,12 @@
import traceback
import netlib.exceptions
from mitmproxy import log
from mitmproxy import controller
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import http
from mitmproxy import flow
from mitmproxy import connections
from netlib.http import http1
from netlib import basethread
@ -14,42 +17,42 @@ from netlib import basethread
class RequestReplayThread(basethread.BaseThread):
name = "RequestReplayThread"
def __init__(self, config, flow, event_queue, should_exit):
def __init__(self, config, f, event_queue, should_exit):
"""
event_queue can be a queue or None, if no scripthooks should be
processed.
"""
self.config, self.flow = config, flow
flow.live = True
self.config, self.f = config, f
f.live = True
if event_queue:
self.channel = controller.Channel(event_queue, should_exit)
else:
self.channel = None
super().__init__(
"RequestReplay (%s)" % flow.request.url
"RequestReplay (%s)" % f.request.url
)
def run(self):
r = self.flow.request
r = self.f.request
first_line_format_backup = r.first_line_format
server = None
try:
self.flow.response = None
self.f.response = None
# If we have a channel, run script hooks.
if self.channel:
request_reply = self.channel.ask("request", self.flow)
if isinstance(request_reply, models.HTTPResponse):
self.flow.response = request_reply
request_reply = self.channel.ask("request", self.f)
if isinstance(request_reply, http.HTTPResponse):
self.f.response = request_reply
if not self.flow.response:
if not self.f.response:
# In all modes, we directly connect to the server displayed
if self.config.options.mode == "upstream":
server_address = self.config.upstream_server.address
server = models.ServerConnection(server_address, (self.config.options.listen_host, 0))
server = connections.ServerConnection(server_address, (self.config.options.listen_host, 0))
server.connect()
if r.scheme == "https":
connect_request = models.make_connect_request((r.data.host, r.port))
connect_request = http.make_connect_request((r.data.host, r.port))
server.wfile.write(http1.assemble_request(connect_request))
server.wfile.flush()
resp = http1.read_response(
@ -61,46 +64,57 @@ class RequestReplayThread(basethread.BaseThread):
raise exceptions.ReplayException("Upstream server refuses CONNECT request")
server.establish_ssl(
self.config.clientcerts,
sni=self.flow.server_conn.sni
sni=self.f.server_conn.sni
)
r.first_line_format = "relative"
else:
r.first_line_format = "absolute"
else:
server_address = (r.host, r.port)
server = models.ServerConnection(server_address, (self.config.options.listen_host, 0))
server = connections.ServerConnection(
server_address,
(self.config.options.listen_host, 0)
)
server.connect()
if r.scheme == "https":
server.establish_ssl(
self.config.clientcerts,
sni=self.flow.server_conn.sni
sni=self.f.server_conn.sni
)
r.first_line_format = "relative"
server.wfile.write(http1.assemble_request(r))
server.wfile.flush()
self.flow.server_conn = server
self.flow.response = models.HTTPResponse.wrap(http1.read_response(
self.f.server_conn = server
self.f.response = http.HTTPResponse.wrap(
http1.read_response(
server.rfile,
r,
body_size_limit=self.config.options.body_size_limit
))
)
)
if self.channel:
response_reply = self.channel.ask("response", self.flow)
response_reply = self.channel.ask("response", self.f)
if response_reply == exceptions.Kill:
raise exceptions.Kill()
except (exceptions.ReplayException, netlib.exceptions.NetlibException) as e:
self.flow.error = models.Error(str(e))
self.f.error = flow.Error(str(e))
if self.channel:
self.channel.ask("error", self.flow)
self.channel.ask("error", self.f)
except exceptions.Kill:
# Kill should only be raised if there's a channel in the
# first place.
self.channel.tell("log", controller.LogEntry("Connection killed", "info"))
self.channel.tell(
"log",
log.LogEntry("Connection killed", "info")
)
except Exception:
self.channel.tell("log", controller.LogEntry(traceback.format_exc(), "error"))
self.channel.tell(
"log",
log.LogEntry(traceback.format_exc(), "error")
)
finally:
r.first_line_format = first_line_format_backup
self.flow.live = False
self.f.live = False
if server:
server.finish()

View File

@ -4,8 +4,8 @@ from OpenSSL import SSL
import netlib.exceptions
import netlib.tcp
from mitmproxy import models
from mitmproxy.models import tcp
from mitmproxy import tcp
from mitmproxy import flow
from mitmproxy.protocol import base
@ -20,8 +20,8 @@ class RawTCPLayer(base.Layer):
self.connect()
if not self.ignore:
flow = models.TCPFlow(self.client_conn, self.server_conn, self)
self.channel.ask("tcp_start", flow)
f = tcp.TCPFlow(self.client_conn, self.server_conn, self)
self.channel.ask("tcp_start", f)
buf = memoryview(bytearray(self.chunk_size))
@ -52,14 +52,14 @@ class RawTCPLayer(base.Layer):
tcp_message = tcp.TCPMessage(dst == server, buf[:size].tobytes())
if not self.ignore:
flow.messages.append(tcp_message)
self.channel.ask("tcp_message", flow)
f.messages.append(tcp_message)
self.channel.ask("tcp_message", f)
dst.sendall(tcp_message.content)
except (socket.error, netlib.exceptions.TcpException, SSL.Error) as e:
if not self.ignore:
flow.error = models.Error("TCP connection closed unexpectedly: {}".format(repr(e)))
self.channel.tell("tcp_error", flow)
f.error = flow.Error("TCP connection closed unexpectedly: {}".format(repr(e)))
self.channel.tell("tcp_error", f)
finally:
if not self.ignore:
self.channel.tell("tcp_end", flow)
self.channel.tell("tcp_end", f)

View File

@ -224,7 +224,7 @@ def get_client_hello(client_conn):
Peek into the socket and read all records that contain the initial client hello message.
client_conn:
The :py:class:`client connection <mitmproxy.models.ClientConnection>`.
The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.
Returns:
The raw handshake packet bytes, without TLS record header(s).
@ -281,7 +281,7 @@ class TlsClientHello:
"""
Peek into the connection, read the initial client hello and parse it to obtain ALPN values.
client_conn:
The :py:class:`client connection <mitmproxy.models.ClientConnection>`.
The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.
Returns:
:py:class:`client hello <mitmproxy.protocol.tls.TlsClientHello>`.
"""

View File

@ -13,7 +13,7 @@ class RootContext:
Attributes:
client_conn:
The :py:class:`client connection <mitmproxy.models.ClientConnection>`.
The :py:class:`client connection <mitmproxy.connections.ClientConnection>`.
channel:
A :py:class:`~mitmproxy.controller.Channel` to communicate with the FlowMaster.
Provides :py:meth:`.ask() <mitmproxy.controller.Channel.ask>` and

View File

@ -4,7 +4,8 @@ import traceback
import netlib.exceptions
from mitmproxy import exceptions
from mitmproxy import models
from mitmproxy import connections
from mitmproxy import http
from mitmproxy import log
from mitmproxy.proxy import modes
from mitmproxy.proxy import root_context
@ -66,7 +67,7 @@ class ConnectionHandler:
def __init__(self, client_conn, client_address, config, channel):
self.config = config
"""@type: mitmproxy.proxy.config.ProxyConfig"""
self.client_conn = models.ClientConnection(
self.client_conn = connections.ClientConnection(
client_conn,
client_address,
None)
@ -135,7 +136,7 @@ class ConnectionHandler:
# we send an HTTP error response, which is both
# understandable by HTTP clients and humans.
try:
error_response = models.make_error_response(502, repr(e))
error_response = http.make_error_response(502, repr(e))
self.client_conn.send(http1.assemble_response(error_response))
except netlib.exceptions.TcpException:
pass

View File

@ -3,7 +3,7 @@ import time
from typing import List
import netlib.basetypes
from mitmproxy.models.flow import Flow
from mitmproxy import flow
class TCPMessage(netlib.basetypes.Serializable):
@ -34,7 +34,7 @@ class TCPMessage(netlib.basetypes.Serializable):
)
class TCPFlow(Flow):
class TCPFlow(flow.Flow):
"""
A TCPFlow is a simplified representation of a TCP session.
@ -44,7 +44,7 @@ class TCPFlow(Flow):
super().__init__("tcp", client_conn, server_conn, live)
self.messages = [] # type: List[TCPMessage]
_stateobject_attributes = Flow._stateobject_attributes.copy()
_stateobject_attributes = flow.Flow._stateobject_attributes.copy()
_stateobject_attributes.update(
messages=List[TCPMessage]
)

View File

View File

@ -750,7 +750,7 @@ def common_options(parser):
def mitmproxy():
# Don't import mitmproxy.console for mitmdump, urwid is not available on all
# Don't import mitmproxy.tools.console for mitmdump, urwid is not available on all
# platforms.
from .console import palettes

View File

@ -0,0 +1,4 @@
from mitmproxy.tools.console import master
__all__ = ["master"]

View File

@ -8,7 +8,7 @@ import urwid.util
import netlib
from mitmproxy import utils
from mitmproxy.console import signals
from mitmproxy.tools.console import signals
from mitmproxy import export
from netlib import human

View File

@ -1,6 +1,6 @@
import urwid
from mitmproxy.console import common, searchable
from mitmproxy.tools.console import common, searchable
from netlib import human

View File

@ -2,8 +2,8 @@ import urwid
import netlib.http.url
from mitmproxy import exceptions
from mitmproxy.console import common
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
from mitmproxy import export

View File

@ -7,14 +7,14 @@ from mitmproxy import exceptions
from typing import Optional, Union # noqa
from mitmproxy import contentviews
from mitmproxy import models
from mitmproxy import http
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 mitmproxy.tools.console import common
from mitmproxy.tools.console import flowdetailview
from mitmproxy.tools.console import grideditor
from mitmproxy.tools.console import searchable
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import tabs
from mitmproxy import export
from netlib.http import Headers
from netlib.http import status_codes
@ -100,7 +100,7 @@ footer = [
class FlowViewHeader(urwid.WidgetWrap):
def __init__(self, master: "mitmproxy.console.master.ConsoleMaster", f: models.HTTPFlow):
def __init__(self, master: "mitmproxy.console.master.ConsoleMaster", f: http.HTTPFlow):
self.master = master
self.flow = f
self._w = common.format_flow(
@ -208,7 +208,7 @@ class FlowView(tabs.Tabs):
if error:
signals.add_log(error, "error")
# Give hint that you have to tab for the response.
if description == "No content" and isinstance(message, models.HTTPRequest):
if description == "No content" and isinstance(message, http.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.
@ -373,7 +373,7 @@ class FlowView(tabs.Tabs):
message = self.flow.request
else:
if not self.flow.response:
self.flow.response = models.HTTPResponse.make(200, b"")
self.flow.response = http.HTTPResponse.make(200, b"")
message = self.flow.response
self.flow.backup()
@ -500,7 +500,7 @@ class FlowView(tabs.Tabs):
signals.flow_change.send(self, flow = self.flow)
def keypress(self, size, key):
conn = None # type: Optional[Union[models.HTTPRequest, models.HTTPResponse]]
conn = None # type: Optional[Union[http.HTTPRequest, http.HTTPResponse]]
if self.tab_offset == TAB_REQ:
conn = self.flow.request
elif self.tab_offset == TAB_RESP:

View File

@ -9,8 +9,8 @@ from typing import Sequence
from typing import Tuple
import urwid
from mitmproxy.console import common
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
FOOTER = [
('heading_key', "enter"), ":edit ",

View File

@ -2,8 +2,8 @@ import os
from typing import Callable, Optional
import urwid
from mitmproxy.console import signals
from mitmproxy.console.grideditor import base
from mitmproxy.tools.console import signals
from mitmproxy.tools.console.grideditor import base
from netlib import strutils

View File

@ -1,6 +1,6 @@
import urwid
from mitmproxy.console.grideditor import base
from mitmproxy.console import signals
from mitmproxy.tools.console.grideditor import base
from mitmproxy.tools.console import signals
from netlib.http import cookies

View File

@ -5,8 +5,8 @@ In a nutshell, text columns are actually a proxy class for byte columns,
which just encode/decodes contents.
"""
from mitmproxy.console import signals
from mitmproxy.console.grideditor import col_bytes
from mitmproxy.tools.console import signals
from mitmproxy.tools.console.grideditor import col_bytes
class Column(col_bytes.Column):

View File

@ -3,12 +3,12 @@ import urwid
from mitmproxy import exceptions
from mitmproxy import flowfilter
from mitmproxy.addons import script
from mitmproxy.console import common
from mitmproxy.console.grideditor import base
from mitmproxy.console.grideditor import col_bytes
from mitmproxy.console.grideditor import col_text
from mitmproxy.console.grideditor import col_subgrid
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console.grideditor import base
from mitmproxy.tools.console.grideditor import col_bytes
from mitmproxy.tools.console.grideditor import col_text
from mitmproxy.tools.console.grideditor import col_subgrid
from mitmproxy.tools.console import signals
from netlib.http import user_agents

View File

@ -3,8 +3,8 @@ import platform
import urwid
from mitmproxy import flowfilter
from mitmproxy.console import common
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
from netlib import version

View File

@ -24,16 +24,16 @@ from mitmproxy import flowfilter
from mitmproxy import utils
from mitmproxy.addons import state
import mitmproxy.options
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 mitmproxy.tools.console import flowlist
from mitmproxy.tools.console import flowview
from mitmproxy.tools.console import grideditor
from mitmproxy.tools.console import help
from mitmproxy.tools.console import options
from mitmproxy.tools.console import palettepicker
from mitmproxy.tools.console import palettes
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import statusbar
from mitmproxy.tools.console import window
from mitmproxy.flowfilter import FMarked
from netlib import tcp, strutils

View File

@ -1,11 +1,11 @@
import urwid
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
from mitmproxy.tools.console import common
from mitmproxy.tools.console import grideditor
from mitmproxy.tools.console import palettes
from mitmproxy.tools.console import select
from mitmproxy.tools.console import signals
footer = [
('heading_key', "enter/space"), ":toggle ",

View File

@ -1,9 +1,9 @@
import urwid
from mitmproxy.console import common
from mitmproxy.console import palettes
from mitmproxy.console import select
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console import palettes
from mitmproxy.tools.console import select
from mitmproxy.tools.console import signals
footer = [
('heading_key', "enter/space"), ":select",

View File

@ -1,6 +1,6 @@
import urwid
from mitmproxy.console import signals
from mitmproxy.tools.console import signals
class Highlight(urwid.AttrMap):

View File

@ -1,6 +1,6 @@
import urwid
from mitmproxy.console import common
from mitmproxy.tools.console import common
class _OptionWidget(urwid.WidgetWrap):

View File

@ -3,9 +3,9 @@ import os.path
import urwid
import netlib.http.url
from mitmproxy.console import common
from mitmproxy.console import pathedit
from mitmproxy.console import signals
from mitmproxy.tools.console import common
from mitmproxy.tools.console import pathedit
from mitmproxy.tools.console import signals
from netlib import human

View File

@ -1,6 +1,6 @@
import urwid
from mitmproxy.console import signals
from mitmproxy.tools.console import signals
class Window(urwid.Frame):

View File

@ -2,7 +2,7 @@ import os
import signal
import sys
from mitmproxy import cmdline
from mitmproxy.tools import cmdline
from mitmproxy import exceptions
from mitmproxy.proxy import config
from mitmproxy.proxy import server
@ -47,7 +47,7 @@ def mitmproxy(args=None): # pragma: no cover
print("Error: mitmproxy's console interface is not supported on Windows. "
"You can run mitmdump or mitmweb instead.", file=sys.stderr)
sys.exit(1)
from . import console
from mitmproxy.tools import console
version_check.check_pyopenssl_version()
assert_utf8_env()
@ -79,7 +79,7 @@ def mitmproxy(args=None): # pragma: no cover
def mitmdump(args=None): # pragma: no cover
from . import dump
from mitmproxy.tools import dump
version_check.check_pyopenssl_version()
@ -113,7 +113,7 @@ def mitmdump(args=None): # pragma: no cover
def mitmweb(args=None): # pragma: no cover
from . import web
from mitmproxy.tools import web
version_check.check_pyopenssl_version()

View File

@ -0,0 +1,2 @@
from mitmproxy.tools.web import master
__all__ = ["master"]

View File

@ -11,13 +11,14 @@ import tornado.web
from io import BytesIO
from mitmproxy import flowfilter
from mitmproxy import models
from mitmproxy import flow
from mitmproxy import http
from mitmproxy import contentviews
from mitmproxy import io
from netlib import version
def convert_flow_to_json_dict(flow: models.Flow) -> dict:
def convert_flow_to_json_dict(flow: flow.Flow) -> dict:
"""
Remove flow message content and cert to save transmission space.
@ -34,7 +35,7 @@ def convert_flow_to_json_dict(flow: models.Flow) -> dict:
if flow.error:
f["error"] = flow.error.get_state()
if isinstance(flow, models.HTTPFlow):
if isinstance(flow, http.HTTPFlow):
if flow.request:
f["request"] = {
"method": flow.request.method,
@ -119,7 +120,7 @@ class RequestHandler(BasicAuth, tornado.web.RequestHandler):
return self.application.master.state
@property
def master(self) -> "mitmproxy.web.master.WebMaster":
def master(self) -> "mitmproxy.tools.web.master.WebMaster":
return self.application.master
@property

View File

@ -12,7 +12,7 @@ from mitmproxy import exceptions
from mitmproxy.addons import state
from mitmproxy import options
from mitmproxy import master
from mitmproxy.web import app
from mitmproxy.tools.web import app
from netlib.http import authentication

View File

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

Before

Width:  |  Height:  |  Size: 1005 B

After

Width:  |  Height:  |  Size: 1005 B

View File

Before

Width:  |  Height:  |  Size: 787 B

After

Width:  |  Height:  |  Size: 787 B

View File

Before

Width:  |  Height:  |  Size: 357 KiB

After

Width:  |  Height:  |  Size: 357 KiB

View File

Before

Width:  |  Height:  |  Size: 853 B

After

Width:  |  Height:  |  Size: 853 B

View File

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 921 B

View File

Before

Width:  |  Height:  |  Size: 976 B

After

Width:  |  Height:  |  Size: 976 B

View File

Before

Width:  |  Height:  |  Size: 861 B

After

Width:  |  Height:  |  Size: 861 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,2 +0,0 @@
from mitmproxy.web import master
__all__ = ["master"]

View File

@ -49,9 +49,9 @@ setup(
include_package_data=True,
entry_points={
'console_scripts': [
"mitmproxy = mitmproxy.main:mitmproxy",
"mitmdump = mitmproxy.main:mitmdump",
"mitmweb = mitmproxy.main:mitmweb",
"mitmproxy = mitmproxy.tools.main:mitmproxy",
"mitmdump = mitmproxy.tools.main:mitmdump",
"mitmweb = mitmproxy.tools.main:mitmweb",
"pathod = pathod.pathod_cmdline:go_pathod",
"pathoc = pathod.pathoc_cmdline:go_pathoc"
]

View File

@ -4,8 +4,8 @@ from .. import tutils, mastertest
from mitmproxy.addons import dumper
from mitmproxy import exceptions
from mitmproxy import dump
from mitmproxy import models
from mitmproxy.tools import dump
from mitmproxy import http
from mitmproxy import proxy
import netlib.tutils
import mock
@ -60,7 +60,7 @@ class TestDumper(mastertest.MasterTest):
d.configure(dump.Options(tfile = sio), updated)
flow = tutils.tflow()
flow.request.content = None
flow.response = models.HTTPResponse.wrap(netlib.tutils.tresp())
flow.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
flow.response.content = None
d.response(flow)
assert "content missing" in sio.getvalue()

View File

@ -3,7 +3,7 @@ import io
from mitmproxy.addons import termlog
from mitmproxy import log
from mitmproxy import dump
from mitmproxy.tools import dump
class TestTermLog(mastertest.MasterTest):

View File

@ -1,4 +1,4 @@
import mitmproxy.console.common as common
from mitmproxy.tools.console import common
from .. import tutils

View File

@ -1,4 +1,4 @@
import mitmproxy.console.help as help
import mitmproxy.tools.console.help as help
from .. import tutils

View File

@ -1,9 +1,9 @@
import gc
import netlib.tutils
from mitmproxy import console
from mitmproxy.tools import console
from mitmproxy import proxy
from mitmproxy.console import common
from mitmproxy.tools.console import common
from .. import tutils, mastertest

View File

@ -1,4 +1,4 @@
import mitmproxy.console.palettes as palettes
import mitmproxy.tools.console.palettes as palettes
from .. import tutils

View File

@ -1,6 +1,6 @@
import os
from os.path import normpath
from mitmproxy.console import pathedit
from mitmproxy.tools.console import pathedit
from mock import patch

View File

@ -4,7 +4,10 @@ from . import tutils
import netlib.tutils
from mitmproxy import master
from mitmproxy import io, proxy, models, options
from mitmproxy import io
from mitmproxy import proxy
from mitmproxy import http
from mitmproxy import options
class TestMaster:
@ -19,7 +22,7 @@ class MasterTest:
master.serverconnect(f.server_conn)
master.request(f)
if not f.error:
f.response = models.HTTPResponse.wrap(
f.response = http.HTTPResponse.wrap(
netlib.tutils.tresp(content=content)
)
master.response(f)

View File

@ -1,5 +1,5 @@
import argparse
from mitmproxy import cmdline
from mitmproxy.tools import cmdline
from . import tutils

View File

@ -2,7 +2,9 @@ import os
import io
import mitmproxy.io
from mitmproxy import dump, exceptions, proxy
from mitmproxy.tools import dump
from mitmproxy import exceptions
from mitmproxy import proxy
from . import tutils, mastertest

View File

@ -8,14 +8,11 @@ from mitmproxy import flowfilter, options
from mitmproxy.addons import state
from mitmproxy.contrib import tnetstring
from mitmproxy.exceptions import FlowReadException, Kill
from mitmproxy.models import Error
from mitmproxy.models import Flow
from mitmproxy.models import HTTPFlow
from mitmproxy.models import HTTPRequest
from mitmproxy.models import HTTPResponse
from mitmproxy import flow
from mitmproxy import http
from mitmproxy import connections
from mitmproxy.proxy import ProxyConfig
from mitmproxy.proxy.server import DummyServer
from mitmproxy.models.connections import ClientConnection
from mitmproxy import master
from . import tutils
@ -62,7 +59,7 @@ class TestHTTPFlow:
def test_backup(self):
f = tutils.tflow()
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
f.request.content = b"foo"
assert not f.modified()
f.backup()
@ -81,20 +78,20 @@ class TestHTTPFlow:
def test_getset_state(self):
f = tutils.tflow(resp=True)
state = f.get_state()
assert f.get_state() == HTTPFlow.from_state(
assert f.get_state() == http.HTTPFlow.from_state(
state).get_state()
f.response = None
f.error = Error("error")
f.error = flow.Error("error")
state = f.get_state()
assert f.get_state() == HTTPFlow.from_state(
assert f.get_state() == http.HTTPFlow.from_state(
state).get_state()
f2 = f.copy()
f2.id = f.id # copy creates a different uuid
assert f.get_state() == f2.get_state()
assert not f == f2
f2.error = Error("e2")
f2.error = flow.Error("e2")
assert not f == f2
f.set_state(f2.get_state())
assert f.get_state() == f2.get_state()
@ -215,7 +212,7 @@ class TestState:
assert c.add_flow(newf)
assert c.active_flow_count() == 2
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
assert c.update_flow(f)
assert c.flow_count() == 2
assert c.active_flow_count() == 1
@ -223,7 +220,7 @@ class TestState:
assert not c.update_flow(None)
assert c.active_flow_count() == 1
newf.response = HTTPResponse.wrap(netlib.tutils.tresp())
newf.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
assert c.update_flow(newf)
assert c.active_flow_count() == 0
@ -231,7 +228,7 @@ class TestState:
c = state.State()
f = tutils.tflow()
c.add_flow(f)
f.error = Error("message")
f.error = flow.Error("message")
assert c.update_flow(f)
c = state.State()
@ -255,7 +252,7 @@ class TestState:
c.set_view_filter("~s")
assert c.filter_txt == "~s"
assert len(c.view) == 0
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
c.update_flow(f)
assert len(c.view) == 1
c.set_view_filter(None)
@ -287,7 +284,7 @@ class TestState:
def _add_response(self, state):
f = tutils.tflow()
state.add_flow(f)
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
state.update_flow(f)
def _add_error(self, state):
@ -316,7 +313,7 @@ class TestState:
c.clear()
c.load_flows(flows)
assert isinstance(c.flows[0], Flow)
assert isinstance(c.flows[0], flow.Flow)
def test_accept_all(self):
c = state.State()
@ -447,17 +444,17 @@ class TestFlowMaster:
fm.addons.add(s)
f = tutils.tflow(req=None)
fm.clientconnect(f.client_conn)
f.request = HTTPRequest.wrap(netlib.tutils.treq())
f.request = http.HTTPRequest.wrap(netlib.tutils.treq())
fm.request(f)
assert s.flow_count() == 1
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
fm.response(f)
assert s.flow_count() == 1
fm.clientdisconnect(f.client_conn)
f.error = Error("msg")
f.error = flow.Error("msg")
fm.error(f)
fm.shutdown()
@ -476,7 +473,7 @@ class TestRequest:
assert r.get_state() == r2.get_state()
def test_get_url(self):
r = HTTPRequest.wrap(netlib.tutils.treq())
r = http.HTTPRequest.wrap(netlib.tutils.treq())
assert r.url == "http://address:22/path"
@ -497,7 +494,7 @@ class TestRequest:
assert r.pretty_url == "https://foo.com:22/path"
def test_replace(self):
r = HTTPRequest.wrap(netlib.tutils.treq())
r = http.HTTPRequest.wrap(netlib.tutils.treq())
r.path = "path/foo"
r.headers["Foo"] = "fOo"
r.content = b"afoob"
@ -507,7 +504,7 @@ class TestRequest:
assert r.headers["boo"] == "boo"
def test_constrain_encoding(self):
r = HTTPRequest.wrap(netlib.tutils.treq())
r = http.HTTPRequest.wrap(netlib.tutils.treq())
r.headers["accept-encoding"] = "gzip, oink"
r.constrain_encoding()
assert "oink" not in r.headers["accept-encoding"]
@ -517,7 +514,7 @@ class TestRequest:
assert "oink" not in r.headers["accept-encoding"]
def test_get_content_type(self):
resp = HTTPResponse.wrap(netlib.tutils.tresp())
resp = http.HTTPResponse.wrap(netlib.tutils.tresp())
resp.headers = Headers(content_type="text/plain")
assert resp.headers["content-type"] == "text/plain"
@ -531,7 +528,7 @@ class TestResponse:
assert resp2.get_state() == resp.get_state()
def test_replace(self):
r = HTTPResponse.wrap(netlib.tutils.tresp())
r = http.HTTPResponse.wrap(netlib.tutils.tresp())
r.headers["Foo"] = "fOo"
r.content = b"afoob"
assert r.replace("foo(?i)", "boo") == 3
@ -539,7 +536,7 @@ class TestResponse:
assert r.headers["boo"] == "boo"
def test_get_content_type(self):
resp = HTTPResponse.wrap(netlib.tutils.tresp())
resp = http.HTTPResponse.wrap(netlib.tutils.tresp())
resp.headers = Headers(content_type="text/plain")
assert resp.headers["content-type"] == "text/plain"
@ -547,13 +544,13 @@ class TestResponse:
class TestError:
def test_getset_state(self):
e = Error("Error")
e = flow.Error("Error")
state = e.get_state()
assert Error.from_state(state).get_state() == e.get_state()
assert flow.Error.from_state(state).get_state() == e.get_state()
assert e.copy()
e2 = Error("bar")
e2 = flow.Error("bar")
assert not e == e2
e.set_state(e2.get_state())
assert e.get_state() == e2.get_state()
@ -562,14 +559,14 @@ class TestError:
assert e3.get_state() == e.get_state()
def test_repr(self):
e = Error("yay")
e = flow.Error("yay")
assert repr(e)
class TestClientConnection:
def test_state(self):
c = tutils.tclient_conn()
assert ClientConnection.from_state(c.get_state()).get_state() == \
assert connections.ClientConnection.from_state(c.get_state()).get_state() == \
c.get_state()
c2 = tutils.tclient_conn()

View File

@ -2,10 +2,10 @@ import os
import mock
from OpenSSL import SSL
from mitmproxy import cmdline
from mitmproxy.tools import cmdline
from mitmproxy import options
from mitmproxy.proxy import ProxyConfig
from mitmproxy.models.connections import ServerConnection
from mitmproxy import connections
from mitmproxy.proxy.server import DummyServer, ProxyServer, ConnectionHandler
from mitmproxy.proxy import config
from netlib.exceptions import TcpDisconnect
@ -18,7 +18,7 @@ class TestServerConnection:
def test_simple(self):
self.d = test.Daemon()
sc = ServerConnection((self.d.IFACE, self.d.port))
sc = connections.ServerConnection((self.d.IFACE, self.d.port))
sc.connect()
f = tutils.tflow()
f.server_conn = sc
@ -36,7 +36,7 @@ class TestServerConnection:
def test_terminate_error(self):
self.d = test.Daemon()
sc = ServerConnection((self.d.IFACE, self.d.port))
sc = connections.ServerConnection((self.d.IFACE, self.d.port))
sc.connect()
sc.connection = mock.Mock()
sc.connection.recv = mock.Mock(return_value=False)

View File

@ -6,9 +6,10 @@ import netlib.tutils
from mitmproxy import controller
from mitmproxy import options
from mitmproxy.addons import script
from mitmproxy.models import HTTPResponse, HTTPFlow
from mitmproxy import http
from mitmproxy.proxy.config import HostMatcher, parse_server_spec
from netlib import tcp, http, socks
import netlib.http
from netlib import tcp, socks
from netlib.certutils import SSLCert
from netlib.exceptions import HttpReadDisconnect, HttpException
from netlib.http import authentication, http1
@ -183,9 +184,9 @@ class TcpMixin:
assert n.status_code == 304
assert i.status_code == 305
assert i2.status_code == 306
assert any(f.response.status_code == 304 for f in self.master.state.flows if isinstance(f, HTTPFlow))
assert not any(f.response.status_code == 305 for f in self.master.state.flows if isinstance(f, HTTPFlow))
assert not any(f.response.status_code == 306 for f in self.master.state.flows if isinstance(f, HTTPFlow))
assert any(f.response.status_code == 304 for f in self.master.state.flows if isinstance(f, http.HTTPFlow))
assert not any(f.response.status_code == 305 for f in self.master.state.flows if isinstance(f, http.HTTPFlow))
assert not any(f.response.status_code == 306 for f in self.master.state.flows if isinstance(f, http.HTTPFlow))
# Test that we get the original SSL cert
if self.ssl:
@ -293,7 +294,7 @@ class TestHTTPAuth(tservers.HTTPProxyTest):
h'%s'='%s'
""" % (
self.server.port,
http.authentication.BasicProxyAuth.AUTH_HEADER,
netlib.http.authentication.BasicProxyAuth.AUTH_HEADER,
authentication.assemble_http_basic_auth("basic", "test", "test")
))
assert ret.status_code == 202
@ -310,7 +311,7 @@ class TestHTTPReverseAuth(tservers.ReverseProxyTest):
'/p/202'
h'%s'='%s'
""" % (
http.authentication.BasicWebsiteAuth.AUTH_HEADER,
netlib.http.authentication.BasicWebsiteAuth.AUTH_HEADER,
authentication.assemble_http_basic_auth("basic", "test", "test")
))
assert ret.status_code == 202
@ -790,7 +791,7 @@ class TestStreamRequest(tservers.HTTPProxyTest):
class MasterFakeResponse(tservers.TestMaster):
@controller.handler
def request(self, f):
f.response = HTTPResponse.wrap(netlib.tutils.tresp())
f.response = http.HTTPResponse.wrap(netlib.tutils.tresp())
class TestFakeResponse(tservers.HTTPProxyTest):
@ -869,7 +870,7 @@ class MasterIncomplete(tservers.TestMaster):
@controller.handler
def request(self, f):
resp = HTTPResponse.wrap(netlib.tutils.tresp())
resp = http.HTTPResponse.wrap(netlib.tutils.tresp())
resp.content = None
f.response = resp

View File

@ -5,7 +5,7 @@ utils.CERT_SLEEP_TIME = 0
def test_pkg_data():
assert utils.pkg_data.path("console")
assert utils.pkg_data.path("tools/console")
tutils.raises("does not exist", utils.pkg_data.path, "nonexistent")

View File

@ -1,8 +1,8 @@
import tornado.testing
from mitmproxy import proxy
from mitmproxy.web import app
from mitmproxy.web import master as webmaster
from mitmproxy.tools.web import app
from mitmproxy.tools.web import master as webmaster
class TestApp(tornado.testing.AsyncHTTPTestCase):

View File

@ -1,4 +1,4 @@
from mitmproxy.web import master
from mitmproxy.tools.web import master
from mitmproxy import proxy
from . import mastertest

View File

@ -12,11 +12,10 @@ import io
import netlib.utils
import netlib.tutils
from mitmproxy import controller
from mitmproxy.models import (
ClientConnection, ServerConnection, Error, HTTPRequest, HTTPResponse, HTTPFlow, TCPFlow
)
from mitmproxy.models.tcp import TCPMessage
from mitmproxy.models.flow import Flow
from mitmproxy import connections
from mitmproxy import flow
from mitmproxy import http
from mitmproxy import tcp
def _skip_windows(*args):
@ -48,7 +47,7 @@ def skip_appveyor(fn):
return fn
class DummyFlow(Flow):
class DummyFlow(flow.Flow):
"""A flow that is neither HTTP nor TCP."""
def __init__(self, client_conn, server_conn, live=None):
@ -76,13 +75,13 @@ def ttcpflow(client_conn=True, server_conn=True, messages=True, err=None):
server_conn = tserver_conn()
if messages is True:
messages = [
TCPMessage(True, b"hello"),
TCPMessage(False, b"it's me"),
tcp.TCPMessage(True, b"hello"),
tcp.TCPMessage(False, b"it's me"),
]
if err is True:
err = terr()
f = TCPFlow(client_conn, server_conn)
f = tcp.TCPFlow(client_conn, server_conn)
f.messages = messages
f.error = err
f.reply = controller.DummyReply()
@ -110,11 +109,11 @@ def tflow(client_conn=True, server_conn=True, req=True, resp=None, err=None):
err = terr()
if req:
req = HTTPRequest.wrap(req)
req = http.HTTPRequest.wrap(req)
if resp:
resp = HTTPResponse.wrap(resp)
resp = http.HTTPResponse.wrap(resp)
f = HTTPFlow(client_conn, server_conn)
f = http.HTTPFlow(client_conn, server_conn)
f.request = req
f.response = resp
f.error = err
@ -126,7 +125,7 @@ def tclient_conn():
"""
@return: mitmproxy.proxy.connection.ClientConnection
"""
c = ClientConnection.from_state(dict(
c = connections.ClientConnection.from_state(dict(
address=dict(address=("address", 22), use_ipv6=True),
clientcert=None,
ssl_established=False,
@ -142,7 +141,7 @@ def tserver_conn():
"""
@return: mitmproxy.proxy.connection.ServerConnection
"""
c = ServerConnection.from_state(dict(
c = connections.ServerConnection.from_state(dict(
address=dict(address=("address", 22), use_ipv6=True),
source_address=dict(address=("address", 22), use_ipv6=True),
ip_address=None,
@ -163,7 +162,7 @@ def terr(content="error"):
"""
@return: mitmproxy.protocol.primitives.Error
"""
err = Error(content)
err = flow.Error(content)
return err