aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/libmproxy/web/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'mitmproxy/libmproxy/web/__init__.py')
-rw-r--r--mitmproxy/libmproxy/web/__init__.py215
1 files changed, 215 insertions, 0 deletions
diff --git a/mitmproxy/libmproxy/web/__init__.py b/mitmproxy/libmproxy/web/__init__.py
new file mode 100644
index 00000000..50c49e8d
--- /dev/null
+++ b/mitmproxy/libmproxy/web/__init__.py
@@ -0,0 +1,215 @@
+from __future__ import absolute_import, print_function
+import collections
+import tornado.ioloop
+import tornado.httpserver
+
+from netlib.http import authentication
+
+from .. import controller, flow
+from . import app
+
+
+class Stop(Exception):
+ pass
+
+
+class WebFlowView(flow.FlowView):
+
+ def __init__(self, store):
+ super(WebFlowView, self).__init__(store, None)
+
+ def _add(self, f):
+ super(WebFlowView, self)._add(f)
+ app.ClientConnection.broadcast(
+ type="flows",
+ cmd="add",
+ data=app._strip_content(f.get_state())
+ )
+
+ def _update(self, f):
+ super(WebFlowView, self)._update(f)
+ app.ClientConnection.broadcast(
+ type="flows",
+ cmd="update",
+ data=app._strip_content(f.get_state())
+ )
+
+ def _remove(self, f):
+ super(WebFlowView, self)._remove(f)
+ app.ClientConnection.broadcast(
+ type="flows",
+ cmd="remove",
+ data=f.id
+ )
+
+ def _recalculate(self, flows):
+ super(WebFlowView, self)._recalculate(flows)
+ app.ClientConnection.broadcast(
+ type="flows",
+ cmd="reset"
+ )
+
+
+class WebState(flow.State):
+
+ def __init__(self):
+ super(WebState, self).__init__()
+ self.view._close()
+ self.view = WebFlowView(self.flows)
+
+ self._last_event_id = 0
+ self.events = collections.deque(maxlen=1000)
+
+ def add_event(self, e, level):
+ self._last_event_id += 1
+ entry = {
+ "id": self._last_event_id,
+ "message": e,
+ "level": level
+ }
+ self.events.append(entry)
+ app.ClientConnection.broadcast(
+ type="events",
+ cmd="add",
+ data=entry
+ )
+
+ def clear(self):
+ super(WebState, self).clear()
+ self.events.clear()
+ app.ClientConnection.broadcast(
+ type="events",
+ cmd="reset",
+ data=[]
+ )
+
+
+class Options(object):
+ attributes = [
+ "app",
+ "app_domain",
+ "app_ip",
+ "anticache",
+ "anticomp",
+ "client_replay",
+ "eventlog",
+ "keepserving",
+ "kill",
+ "intercept",
+ "no_server",
+ "refresh_server_playback",
+ "rfile",
+ "scripts",
+ "showhost",
+ "replacements",
+ "rheaders",
+ "setheaders",
+ "server_replay",
+ "stickycookie",
+ "stickyauth",
+ "stream_large_bodies",
+ "verbosity",
+ "wfile",
+ "nopop",
+
+ "wdebug",
+ "wport",
+ "wiface",
+ "wauthenticator",
+ "wsingleuser",
+ "whtpasswd",
+ ]
+
+ def __init__(self, **kwargs):
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+ for i in self.attributes:
+ if not hasattr(self, i):
+ setattr(self, i, None)
+
+ def process_web_options(self, parser):
+ if self.wsingleuser or self.whtpasswd:
+ if self.wsingleuser:
+ if len(self.wsingleuser.split(':')) != 2:
+ return parser.error(
+ "Invalid single-user specification. Please use the format username:password"
+ )
+ username, password = self.wsingleuser.split(':')
+ self.wauthenticator = authentication.PassManSingleUser(username, password)
+ elif self.whtpasswd:
+ try:
+ self.wauthenticator = authentication.PassManHtpasswd(self.whtpasswd)
+ except ValueError as v:
+ return parser.error(v.message)
+ else:
+ self.wauthenticator = None
+
+
+class WebMaster(flow.FlowMaster):
+
+ def __init__(self, server, options):
+ self.options = options
+ super(WebMaster, self).__init__(server, WebState())
+ self.app = app.Application(self, self.options.wdebug, self.options.wauthenticator)
+ if options.rfile:
+ try:
+ self.load_flows_file(options.rfile)
+ except flow.FlowReadError as v:
+ self.add_event(
+ "Could not read flow file: %s" % v,
+ "error"
+ )
+
+ if options.outfile:
+ err = self.start_stream_to_path(
+ options.outfile[0],
+ options.outfile[1]
+ )
+ if err:
+ print >> sys.stderr, "Stream file error:", err
+ sys.exit(1)
+
+ if self.options.app:
+ self.start_app(self.options.app_host, self.options.app_port)
+
+ def tick(self):
+ flow.FlowMaster.tick(self, self.masterq, timeout=0)
+
+ def run(self): # pragma: no cover
+ self.server.start_slave(
+ controller.Slave,
+ controller.Channel(self.masterq, self.should_exit)
+ )
+ iol = tornado.ioloop.IOLoop.instance()
+
+ http_server = tornado.httpserver.HTTPServer(self.app)
+ http_server.listen(self.options.wport)
+
+ tornado.ioloop.PeriodicCallback(self.tick, 5).start()
+ try:
+ iol.start()
+ except (Stop, KeyboardInterrupt):
+ self.shutdown()
+
+ def _process_flow(self, f):
+ if self.state.intercept and self.state.intercept(
+ f) and not f.request.is_replay:
+ f.intercept(self)
+ else:
+ f.reply()
+
+ def handle_request(self, f):
+ super(WebMaster, self).handle_request(f)
+ self._process_flow(f)
+
+ def handle_response(self, f):
+ super(WebMaster, self).handle_response(f)
+ self._process_flow(f)
+
+ def handle_error(self, f):
+ super(WebMaster, self).handle_error(f)
+ self._process_flow(f)
+
+ def add_event(self, e, level="info"):
+ super(WebMaster, self).add_event(e, level)
+ self.state.add_event(e, level)