aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/Makefile2
-rw-r--r--docs/dev/models.rst10
-rw-r--r--docs/dev/testing.rst2
-rw-r--r--docs/index.rst2
-rw-r--r--docs/scripting/mitmproxy.rst6
-rw-r--r--mitmproxy/console/flowdetailview.py2
-rw-r--r--mitmproxy/flow.py14
-rw-r--r--mitmproxy/flow_format_compat.py1
-rw-r--r--mitmproxy/models/__init__.py3
-rw-r--r--mitmproxy/models/connections.py46
-rw-r--r--mitmproxy/models/http.py84
-rw-r--r--netlib/http/request.py1
-rw-r--r--netlib/tcp.py6
-rw-r--r--test/mitmproxy/tutils.py2
14 files changed, 82 insertions, 99 deletions
diff --git a/docs/Makefile b/docs/Makefile
index 74bcda53..b8255107 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -192,4 +192,4 @@ pseudoxml:
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
livehtml:
- sphinx-autobuild -b html -z '../mitmproxy' -z '../../netlib/netlib' -r '___jb_(old|bak)___$$' $(ALLSPHINXOPTS) $(BUILDDIR)/html \ No newline at end of file
+ sphinx-autobuild -b html -z '../mitmproxy' -r '___jb_(old|bak|tmp)___$$' $(ALLSPHINXOPTS) $(BUILDDIR)/html \ No newline at end of file
diff --git a/docs/dev/models.rst b/docs/dev/models.rst
index 7a949941..2eac6783 100644
--- a/docs/dev/models.rst
+++ b/docs/dev/models.rst
@@ -1,7 +1,11 @@
.. _models:
-Models
-======
+Datastructures
+==============
+
+.. automodule:: mitmproxy.models
+ :members: HTTPFlow, HTTPRequest, HTTPResponse
+
.. automodule:: netlib.http
@@ -56,4 +60,4 @@ Models
.. automodule:: mitmproxy.models
:show-inheritance:
- :members: HTTPFlow, Error, ClientConnection, ServerConnection \ No newline at end of file
+ :members: Error, ServerConnection, ClientConnection \ No newline at end of file
diff --git a/docs/dev/testing.rst b/docs/dev/testing.rst
index e3b86bf3..c9ed5164 100644
--- a/docs/dev/testing.rst
+++ b/docs/dev/testing.rst
@@ -10,7 +10,7 @@ suitable extension to the test suite.
Our tests are written for the `py.test`_ or nose_ test frameworks.
At the point where you send your pull request, a command like this:
->>> py.test -n 4 --cov mitmproxy
+>>> py.test --cov mitmproxy --cov netlib
Should give output something like this:
diff --git a/docs/index.rst b/docs/index.rst
index 4bca07d1..d3b6f434 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -52,6 +52,7 @@
:caption: Scripting
scripting/inlinescripts
+ dev/models
scripting/mitmproxy
@@ -73,7 +74,6 @@
dev/protocols
dev/proxy
dev/exceptions
- dev/models
.. Indices and tables
==================
diff --git a/docs/scripting/mitmproxy.rst b/docs/scripting/mitmproxy.rst
index 73450df5..9e331736 100644
--- a/docs/scripting/mitmproxy.rst
+++ b/docs/scripting/mitmproxy.rst
@@ -1,10 +1,10 @@
-mitmproxy
-=========
+FlowMaster
+==========
.. note::
- We strongly encourage you to use :ref:`inlinescripts` rather than mitmproxy.
+ We strongly encourage you to use :ref:`inlinescripts` rather than subclassing mitmproxy's FlowMaster.
- Inline Scripts are equally powerful and provide an easier syntax.
- Most examples are written as inline scripts.
- Multiple inline scripts can be used together.
diff --git a/mitmproxy/console/flowdetailview.py b/mitmproxy/console/flowdetailview.py
index d338b6bc..ca083b10 100644
--- a/mitmproxy/console/flowdetailview.py
+++ b/mitmproxy/console/flowdetailview.py
@@ -23,7 +23,7 @@ def flowdetails(state, flow):
text.append(urwid.Text([("head", "Server Connection:")]))
parts = [
["Address", repr(sc.address)],
- ["Peer Address", repr(sc.peer_address)],
+ ["Resolved Address", repr(sc.ip_address)],
]
text.extend(
diff --git a/mitmproxy/flow.py b/mitmproxy/flow.py
index 246e9f82..cf07ea9a 100644
--- a/mitmproxy/flow.py
+++ b/mitmproxy/flow.py
@@ -842,21 +842,15 @@ class FlowMaster(controller.Master):
"""
this method creates a new artificial and minimalist request also adds it to flowlist
"""
- c = ClientConnection.from_state(dict(
- address=dict(address=(host, port), use_ipv6=False),
- clientcert=None,
- ssl_established=False,
- timestamp_start=None,
- timestamp_end=None,
- timestamp_ssl_setup=None
- ))
+ c = ClientConnection.make_dummy(("", 0))
+ s = ServerConnection.make_dummy((host, port))
s = ServerConnection.from_state(dict(
address=dict(address=(host, port), use_ipv6=False),
- peer_address=None,
+ ip_address=None,
cert=None,
sni=host,
- source_address=dict(address=('', 0), use_ipv6=False),
+ source_address=dict(address=("", 0), use_ipv6=False),
ssl_established=True,
timestamp_start=None,
timestamp_tcp_setup=None,
diff --git a/mitmproxy/flow_format_compat.py b/mitmproxy/flow_format_compat.py
index 84da3495..8478367c 100644
--- a/mitmproxy/flow_format_compat.py
+++ b/mitmproxy/flow_format_compat.py
@@ -41,6 +41,7 @@ def convert_016_017(data):
def convert_017_018(data):
+ data["server_conn"]["ip_address"] = data["server_conn"].pop("peer_address")
data["version"] = (0, 18)
return data
diff --git a/mitmproxy/models/__init__.py b/mitmproxy/models/__init__.py
index 653b19fd..f5f0213a 100644
--- a/mitmproxy/models/__init__.py
+++ b/mitmproxy/models/__init__.py
@@ -1,9 +1,10 @@
from __future__ import (absolute_import, print_function, division)
from .http import (
- HTTPFlow, HTTPRequest, HTTPResponse, Headers, decoded,
+ 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
diff --git a/mitmproxy/models/connections.py b/mitmproxy/models/connections.py
index 14545842..91590bca 100644
--- a/mitmproxy/models/connections.py
+++ b/mitmproxy/models/connections.py
@@ -10,6 +10,17 @@ from .. import stateobject, utils
class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
+ """
+ A client connection
+
+ Attributes:
+ address: Remote address
+ ssl_established: True if TLS is established, False otherwise
+ clientcert: The TLS client certificate
+ timestamp_start: Connection start timestamp
+ timestamp_ssl_setup: TLS established timestamp
+ timestamp_end: Connection end timestamp
+ """
def __init__(self, client_connection, address, server):
# Eventually, this object is restored from state. We don't have a
# connection then.
@@ -47,11 +58,11 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
_stateobject_attributes = dict(
address=tcp.Address,
- clientcert=certutils.SSLCert,
ssl_established=bool,
+ clientcert=certutils.SSLCert,
timestamp_start=float,
+ timestamp_ssl_setup=float,
timestamp_end=float,
- timestamp_ssl_setup=float
)
def copy(self):
@@ -90,6 +101,22 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
class ServerConnection(tcp.TCPClient, stateobject.StateObject):
+ """
+ A server connection
+
+ Attributes:
+ address: Remote address. Can be both a domain or an IP address.
+ ip_address: Resolved remote IP address.
+ source_address: Local IP address
+ ssl_established: True if TLS is established, False otherwise
+ cert: The certificate presented by the remote during the TLS handshake
+ sni: Server Name Indication sent by the proxy during the TLS handshake
+ via: The underlying server connection (e.g. the connection to the upstream proxy in upstream proxy mode)
+ timestamp_start: Connection start timestamp
+ timestamp_tcp_setup: TCP ACK received timestamp
+ timestamp_ssl_setup: TLS established timestamp
+ timestamp_end: Connection end timestamp
+ """
def __init__(self, address, source_address=None):
tcp.TCPClient.__init__(self, address, source_address)
@@ -123,16 +150,16 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
return self.ssl_established
_stateobject_attributes = dict(
- timestamp_start=float,
- timestamp_end=float,
- timestamp_tcp_setup=float,
- timestamp_ssl_setup=float,
address=tcp.Address,
- peer_address=tcp.Address,
+ ip_address=tcp.Address,
source_address=tcp.Address,
- cert=certutils.SSLCert,
ssl_established=bool,
- sni=str
+ cert=certutils.SSLCert,
+ sni=str,
+ timestamp_start=float,
+ timestamp_tcp_setup=float,
+ timestamp_ssl_setup=float,
+ timestamp_end=float,
)
@classmethod
@@ -145,6 +172,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
def make_dummy(cls, address):
return cls.from_state(dict(
address=dict(address=address, use_ipv6=False),
+ ip_address=dict(address=address, use_ipv6=False),
cert=None,
sni=None,
source_address=dict(address=('', 0), use_ipv6=False),
diff --git a/mitmproxy/models/http.py b/mitmproxy/models/http.py
index 08fc5e46..77a809cf 100644
--- a/mitmproxy/models/http.py
+++ b/mitmproxy/models/http.py
@@ -1,14 +1,9 @@
from __future__ import (absolute_import, print_function, division)
import cgi
-import copy
-import warnings
-from email.utils import parsedate_tz, formatdate, mktime_tz
-import time
from netlib import encoding
-from netlib.http import status_codes, Headers, Request, Response, decoded
+from netlib.http import status_codes, Headers, Request, Response
from netlib.tcp import Address
-from .. import utils
from .. import version
from .flow import Flow
@@ -30,41 +25,9 @@ class MessageMixin(object):
class HTTPRequest(MessageMixin, Request):
"""
- An HTTP request.
-
- Exposes the following attributes:
-
- method: HTTP method
-
- scheme: URL scheme (http/https)
-
- host: Target hostname of the request. This is not neccessarily the
- directy upstream server (which could be another proxy), but it's always
- the target server we want to reach at the end. This attribute is either
- inferred from the request itself (absolute-form, authority-form) or from
- the connection metadata (e.g. the host in reverse proxy mode).
-
- port: Destination port
-
- path: Path portion of the URL (not present in authority-form)
-
- http_version: HTTP version, e.g. "HTTP/1.1"
-
- headers: Headers object
-
- content: Content of the request, the value is None if there is content
- associated, but not present.
-
- first_line_format: The request form. The following values are possible:
-
- - relative (GET /index.html, OPTIONS *) (origin form or asterisk form)
- - absolute (GET http://example.com:80/index.html)
- - authority-form (CONNECT example.com:443)
- Details: http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25#section-5.3
-
- timestamp_start: Timestamp indicating when request transmission started
-
- timestamp_end: Timestamp indicating when request transmission ended
+ A mitmproxy HTTP request.
+ This is a very thin wrapper on top of :py:class:`netlib.http.Request` and
+ may be removed in the future.
"""
def __init__(
@@ -123,6 +86,9 @@ class HTTPRequest(MessageMixin, Request):
@classmethod
def wrap(self, request):
+ """
+ Wraps an existing :py:class:`netlib.http.Request`.
+ """
req = HTTPRequest(
first_line_format=request.data.first_line_format,
method=request.data.method,
@@ -141,27 +107,12 @@ class HTTPRequest(MessageMixin, Request):
def __hash__(self):
return id(self)
-class HTTPResponse(MessageMixin, Response):
+class HTTPResponse(MessageMixin, Response):
"""
- An HTTP response.
-
- Exposes the following attributes:
-
- http_version: HTTP version, e.g. "HTTP/1.1"
-
- status_code: HTTP response status code
-
- msg: HTTP response message
-
- headers: Headers object
-
- content: Content of the response, the value is None if there is content
- associated, but not present.
-
- timestamp_start: Timestamp indicating when request transmission started
-
- timestamp_end: Timestamp indicating when request transmission ended
+ A mitmproxy HTTP response.
+ This is a very thin wrapper on top of :py:class:`netlib.http.Response` and
+ may be removed in the future.
"""
def __init__(
@@ -192,6 +143,9 @@ class HTTPResponse(MessageMixin, Response):
@classmethod
def wrap(self, response):
+ """
+ Wraps an existing :py:class:`netlib.http.Response`.
+ """
resp = HTTPResponse(
http_version=response.data.http_version,
status_code=response.data.status_code,
@@ -211,11 +165,11 @@ class HTTPFlow(Flow):
transaction.
Attributes:
- request: HTTPRequest object
- response: HTTPResponse object
- error: Error object
- server_conn: ServerConnection object
- client_conn: ClientConnection object
+ request: :py:class:`HTTPRequest` object
+ response: :py:class:`HTTPResponse` object
+ error: :py:class:`Error` object
+ server_conn: :py:class:`ServerConnection` object
+ client_conn: :py:class:`ClientConnection` object
intercepted: Is this flow currently being intercepted?
live: Does this flow have a live client connection?
diff --git a/netlib/http/request.py b/netlib/http/request.py
index 692ba30f..160ce3a3 100644
--- a/netlib/http/request.py
+++ b/netlib/http/request.py
@@ -18,6 +18,7 @@ from .message import Message, _native, _always_bytes, MessageData
# https://bugzilla.mozilla.org/show_bug.cgi?id=45891
host_header_re = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$")
+
class RequestData(MessageData):
def __init__(self, first_line_format, method, scheme, host, port, path, http_version, headers=None, content=None,
timestamp_start=None, timestamp_end=None):
diff --git a/netlib/tcp.py b/netlib/tcp.py
index 04aa868b..d26bb5f7 100644
--- a/netlib/tcp.py
+++ b/netlib/tcp.py
@@ -458,11 +458,11 @@ class _Connection(object):
def __init__(self, connection):
if connection:
self.connection = connection
- self.peer_address = Address(connection.getpeername())
+ self.ip_address = Address(connection.getpeername())
self._makefile()
else:
self.connection = None
- self.peer_address = None
+ self.ip_address = None
self.rfile = None
self.wfile = None
@@ -708,7 +708,7 @@ class TCPClient(_Connection):
'Error connecting to "%s": %s' %
(self.address.host, err))
self.connection = connection
- self.peer_address = Address(connection.getpeername())
+ self.ip_address = Address(connection.getpeername())
self._makefile()
def settimeout(self, n):
diff --git a/test/mitmproxy/tutils.py b/test/mitmproxy/tutils.py
index 191eb966..d51ac185 100644
--- a/test/mitmproxy/tutils.py
+++ b/test/mitmproxy/tutils.py
@@ -100,7 +100,7 @@ def tserver_conn():
c = ServerConnection.from_state(dict(
address=dict(address=("address", 22), use_ipv6=True),
source_address=dict(address=("address", 22), use_ipv6=True),
- peer_address=None,
+ ip_address=None,
cert=None,
timestamp_start=1,
timestamp_tcp_setup=2,