aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2013-03-25 09:20:26 +1300
committerAldo Cortesi <aldo@nullcube.com>2013-03-25 09:20:26 +1300
commite3fd0e838d67d2e73176a7650d371b6ab59333e0 (patch)
tree8cd51143da16b6fad3e34dfc8e23a43582e38cbd
parent98e4421a90854ef3462377909904c8397f107c43 (diff)
downloadmitmproxy-e3fd0e838d67d2e73176a7650d371b6ab59333e0.tar.gz
mitmproxy-e3fd0e838d67d2e73176a7650d371b6ab59333e0.tar.bz2
mitmproxy-e3fd0e838d67d2e73176a7650d371b6ab59333e0.zip
Add a basic built-in web app.
-rw-r--r--libmproxy/app.py8
-rw-r--r--libmproxy/cmdline.py9
-rw-r--r--libmproxy/flow.py12
-rw-r--r--libmproxy/proxy.py22
-rw-r--r--test/test_server.py12
-rw-r--r--test/tservers.py15
6 files changed, 68 insertions, 10 deletions
diff --git a/libmproxy/app.py b/libmproxy/app.py
new file mode 100644
index 00000000..666b4d48
--- /dev/null
+++ b/libmproxy/app.py
@@ -0,0 +1,8 @@
+import flask
+
+mapp = flask.Flask(__name__)
+
+@mapp.route("/")
+def hello():
+ return "mitmproxy"
+
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index 1d5902a9..b76792cf 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -163,7 +163,7 @@ def get_common_options(options):
def common_options(parser):
parser.add_argument(
- "-a",
+ "-b",
action="store", type = str, dest="addr", default='',
help = "Address to bind proxy to (defaults to all interfaces)"
)
@@ -261,6 +261,13 @@ def common_options(parser):
help="Don't connect to upstream server to look up certificate details."
)
+ group = parser.add_argument_group("Web App")
+ group.add_argument(
+ "-a",
+ action="store_true", dest="app", default=False,
+ help="Enable the mitmproxy web app."
+ )
+
group = parser.add_argument_group("Client Replay")
group.add_argument(
"-c",
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index d33a3108..6d77fd88 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -23,6 +23,7 @@ import tnetstring, filt, script, utils, encoding, proxy
from email.utils import parsedate_tz, formatdate, mktime_tz
from netlib import odict, http, certutils
import controller, version
+import app
HDR_FORM_URLENCODED = "application/x-www-form-urlencoded"
CONTENT_MISSING = 0
@@ -42,13 +43,13 @@ class ReplaceHooks:
def add(self, fpatt, rex, s):
"""
- Add a replacement hook.
+ add a replacement hook.
- fpatt: A string specifying a filter pattern.
- rex: A regular expression.
- s: The replacement string
+ fpatt: a string specifying a filter pattern.
+ rex: a regular expression.
+ s: the replacement string
- Returns True if hook was added, False if the pattern could not be
+ returns true if hook was added, false if the pattern could not be
parsed.
"""
cpatt = filt.parse(fpatt)
@@ -1352,6 +1353,7 @@ class FlowMaster(controller.Master):
self.setheaders = SetHeaders()
self.stream = None
+ app.mapp.config["PMASTER"] = self
def add_event(self, e, level="info"):
"""
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index ad7be354..3fac17b8 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -17,8 +17,11 @@ import shutil, tempfile, threading
import SocketServer
from OpenSSL import SSL
from netlib import odict, tcp, http, wsgi, certutils, http_status, http_auth
-import utils, flow, version, platform, controller
+import utils, flow, version, platform, controller, app
+
+APP_DOMAIN = "mitm"
+APP_IP = "1.1.1.1"
KILL = 0
@@ -36,8 +39,8 @@ class Log:
class ProxyConfig:
- def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
- assert not (reverse_proxy and transparent_proxy)
+ def __init__(self, app=False, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
+ self.app = app
self.certfile = certfile
self.cacert = cacert
self.clientcerts = clientcerts
@@ -85,6 +88,7 @@ class ServerConnection(tcp.TCPClient):
pass
+
class RequestReplayThread(threading.Thread):
def __init__(self, config, flow, masterq):
self.config, self.flow, self.channel = config, flow, controller.Channel(masterq)
@@ -497,6 +501,17 @@ class ProxyServer(tcp.TCPServer):
raise ProxyServerError('Error starting proxy server: ' + v.strerror)
self.channel = None
self.apps = AppRegistry()
+ if config.app:
+ self.apps.add(
+ app.mapp,
+ APP_DOMAIN,
+ 80
+ )
+ self.apps.add(
+ app.mapp,
+ APP_IP,
+ 80
+ )
def start_slave(self, klass, channel):
slave = klass(channel, self)
@@ -629,6 +644,7 @@ def process_proxy_options(parser, options):
authenticator = http_auth.NullProxyAuth(None)
return ProxyConfig(
+ app = options.app,
certfile = options.cert,
cacert = cacert,
clientcerts = options.clientcerts,
diff --git a/test/test_server.py b/test/test_server.py
index f12fbcee..c20b0cea 100644
--- a/test/test_server.py
+++ b/test/test_server.py
@@ -53,7 +53,16 @@ class CommonMixin:
assert "Bad Request" in t.rfile.readline()
-class TestHTTP(tservers.HTTPProxTest, CommonMixin):
+
+class AppMixin:
+ def test_app(self):
+ ret = self.app("/")
+ assert ret.status_code == 200
+ assert "mitmproxy" in ret.content
+
+
+
+class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
def test_app_err(self):
p = self.pathoc()
ret = p.request("get:'http://errapp/'")
@@ -135,6 +144,7 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin):
assert req.status_code == 400
+
class TestHTTPAuth(tservers.HTTPProxTest):
authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm")
def test_auth(self):
diff --git a/test/tservers.py b/test/tservers.py
index 0c2f8c2f..91ce4dc0 100644
--- a/test/tservers.py
+++ b/test/tservers.py
@@ -84,6 +84,7 @@ class ProxTestBase:
no_upstream_cert = cls.no_upstream_cert,
cacert = tutils.test_data.path("data/serverkey.pem"),
authenticator = cls.authenticator,
+ app = True,
**pconf
)
tmaster = cls.masterclass(cls.tqueue, config)
@@ -156,6 +157,17 @@ class HTTPProxTest(ProxTestBase):
q = "get:'%s/p/%s'"%(self.server.urlbase, spec)
return p.request(q)
+ def app(self, page):
+ if self.ssl:
+ p = libpathod.pathoc.Pathoc("127.0.0.1", self.proxy.port, True)
+ print "PRE"
+ p.connect((proxy.APP_IP, 80))
+ print "POST"
+ return p.request("get:'/%s'"%page)
+ else:
+ p = self.pathoc()
+ return p.request("get:'http://%s/%s'"%(proxy.APP_DOMAIN, page))
+
class TResolver:
def __init__(self, port):
@@ -234,3 +246,6 @@ class ReverseProxTest(ProxTestBase):
q = "get:'/p/%s'"%spec
return p.request(q)
+
+
+