aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2014-09-17 09:40:25 +1200
committerAldo Cortesi <aldo@nullcube.com>2014-09-17 09:40:25 +1200
commitf7da58ca9b8b3dc33f5a9b57999b07f99db5bc63 (patch)
tree956984514258b8ebde4548b2032202447ee37dc7 /libmproxy
parent4f56b76b2c811006045c3226848aa5e122fb36ab (diff)
downloadmitmproxy-f7da58ca9b8b3dc33f5a9b57999b07f99db5bc63.tar.gz
mitmproxy-f7da58ca9b8b3dc33f5a9b57999b07f99db5bc63.tar.bz2
mitmproxy-f7da58ca9b8b3dc33f5a9b57999b07f99db5bc63.zip
Basic websocket connection, code cleanup.
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/flow.py24
-rw-r--r--libmproxy/protocol/primitives.py43
-rw-r--r--libmproxy/web/__init__.py6
-rw-r--r--libmproxy/web/app.py22
-rw-r--r--libmproxy/web/static/js/app.js25
5 files changed, 74 insertions, 46 deletions
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index c246894c..b9095a02 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -2,11 +2,10 @@
This module provides more sophisticated flow tracking and provides filtering and interception facilities.
"""
from __future__ import absolute_import
-import base64
-import hashlib, Cookie, cookielib, re, threading
-import os
-import flask
-import requests
+import hashlib
+import Cookie
+import cookielib
+import re
from netlib import odict, wsgi
import netlib.http
from . import controller, protocol, tnetstring, filt, script, version
@@ -151,10 +150,13 @@ class StreamLargeBodies(object):
def run(self, flow, is_request):
r = flow.request if is_request else flow.response
code = flow.response.code if flow.response else None
- expected_size = netlib.http.expected_http_body_size(r.headers, is_request, flow.request.method, code)
+ expected_size = netlib.http.expected_http_body_size(
+ r.headers, is_request, flow.request.method, code
+ )
if not (0 <= expected_size <= self.max_size):
r.stream = True
+
class ClientPlaybackState:
def __init__(self, flows, exit):
self.flows, self.exit = flows, exit
@@ -645,11 +647,11 @@ class FlowMaster(controller.Master):
f.error = None
self.process_new_request(f)
rt = http.RequestReplayThread(
- self.server.config,
- f,
- self.masterq,
- self.should_exit
- )
+ self.server.config,
+ f,
+ self.masterq,
+ self.should_exit
+ )
rt.start() # pragma: no cover
if block:
rt.join()
diff --git a/libmproxy/protocol/primitives.py b/libmproxy/protocol/primitives.py
index 160c50c7..ecf24fd7 100644
--- a/libmproxy/protocol/primitives.py
+++ b/libmproxy/protocol/primitives.py
@@ -12,10 +12,10 @@ class Error(stateobject.SimpleStateObject):
"""
An Error.
- This is distinct from an protocol error response (say, a HTTP code 500), which
- is represented by a normal HTTPResponse object. This class is responsible
- for indicating errors that fall outside of normal protocol communications,
- like interrupted connections, timeouts, protocol errors.
+ This is distinct from an protocol error response (say, a HTTP code 500),
+ which is represented by a normal HTTPResponse object. This class is
+ responsible for indicating errors that fall outside of normal protocol
+ communications, like interrupted connections, timeouts, protocol errors.
Exposes the following attributes:
@@ -42,7 +42,9 @@ class Error(stateobject.SimpleStateObject):
@classmethod
def _from_state(cls, state):
- f = cls(None) # the default implementation assumes an empty constructor. Override accordingly.
+ # the default implementation assumes an empty constructor. Override
+ # accordingly.
+ f = cls(None)
f._load_state(state)
return f
@@ -133,31 +135,35 @@ class ProtocolHandler(object):
def handle_messages(self):
"""
- This method gets called if a client connection has been made. Depending on the proxy settings,
- a server connection might already exist as well.
+ This method gets called if a client connection has been made. Depending
+ on the proxy settings, a server connection might already exist as well.
"""
raise NotImplementedError # pragma: nocover
def handle_server_reconnect(self, state):
"""
- This method gets called if a server connection needs to reconnect and there's a state associated
- with the server connection (e.g. a previously-sent CONNECT request or a SOCKS proxy request).
- This method gets called after the connection has been restablished but before SSL is established.
+ This method gets called if a server connection needs to reconnect and
+ there's a state associated with the server connection (e.g. a
+ previously-sent CONNECT request or a SOCKS proxy request). This method
+ gets called after the connection has been restablished but before SSL is
+ established.
"""
raise NotImplementedError # pragma: nocover
def handle_error(self, error):
"""
- This method gets called should there be an uncaught exception during the connection.
- This might happen outside of handle_messages, e.g. if the initial SSL handshake fails in transparent mode.
+ This method gets called should there be an uncaught exception during the
+ connection. This might happen outside of handle_messages, e.g. if the
+ initial SSL handshake fails in transparent mode.
"""
raise error # pragma: nocover
class LiveConnection(object):
"""
- This facade allows interested parties (FlowMaster, inline scripts) to interface with a live connection,
- without requiring to expose the internals of the ConnectionHandler.
+ This facade allows interested parties (FlowMaster, inline scripts) to
+ interface with a live connection, without requiring to expose the internals
+ of the ConnectionHandler.
"""
def __init__(self, c):
self.c = c
@@ -193,7 +199,9 @@ class LiveConnection(object):
if not self._backup_server_conn and not persistent_change:
self._backup_server_conn = self.c.server_conn
self.c.server_conn = None
- else: # This is at least the second temporary change. We can kill the current connection.
+ else:
+ # This is at least the second temporary change. We can kill the
+ # current connection.
self.c.del_server_connection()
self.c.set_server_address(address)
@@ -204,8 +212,9 @@ class LiveConnection(object):
return False
def restore_server(self):
- # TODO: Similar to _backup_server_conn, introduce _cache_server_conn, which keeps the changed connection open
- # This may be beneficial if a user is rewriting all requests from http to https or similar.
+ # TODO: Similar to _backup_server_conn, introduce _cache_server_conn,
+ # which keeps the changed connection open This may be beneficial if a
+ # user is rewriting all requests from http to https or similar.
if not self._backup_server_conn:
return
diff --git a/libmproxy/web/__init__.py b/libmproxy/web/__init__.py
index 8f98060c..044cb0cd 100644
--- a/libmproxy/web/__init__.py
+++ b/libmproxy/web/__init__.py
@@ -58,6 +58,7 @@ class Options(object):
class WebMaster(flow.FlowMaster):
def __init__(self, server, options):
self.options = options
+ self.app = app.Application(self.options.wdebug)
flow.FlowMaster.__init__(self, server, WebState())
def tick(self):
@@ -70,9 +71,7 @@ class WebMaster(flow.FlowMaster):
)
iol = tornado.ioloop.IOLoop.instance()
- http_server = tornado.httpserver.HTTPServer(
- app.Application(self.options.wdebug)
- )
+ http_server = tornado.httpserver.HTTPServer(self.app)
http_server.listen(self.options.wport)
tornado.ioloop.PeriodicCallback(self.tick, 5).start()
@@ -82,6 +81,7 @@ class WebMaster(flow.FlowMaster):
self.shutdown()
def handle_request(self, f):
+ print f
flow.FlowMaster.handle_request(self, f)
if f:
f.reply()
diff --git a/libmproxy/web/app.py b/libmproxy/web/app.py
index 31b299a3..e9bcc526 100644
--- a/libmproxy/web/app.py
+++ b/libmproxy/web/app.py
@@ -1,6 +1,7 @@
-
import os.path
import tornado.web
+import tornado.websocket
+import logging
class IndexHandler(tornado.web.RequestHandler):
@@ -8,10 +9,29 @@ class IndexHandler(tornado.web.RequestHandler):
self.render("index.html")
+class ClientConnection(tornado.websocket.WebSocketHandler):
+ connections = set()
+
+ def open(self):
+ ClientConnection.connections.add(self)
+
+ def on_close(self):
+ ClientConnection.connections.remove(self)
+
+ @classmethod
+ def broadcast(cls, type, data):
+ for conn in cls.connections:
+ try:
+ conn.write_message(type, data)
+ except:
+ logging.error("Error sending message", exc_info=True)
+
+
class Application(tornado.web.Application):
def __init__(self, debug):
handlers = [
(r"/", IndexHandler),
+ (r"/updates", ClientConnection),
]
settings = dict(
template_path=os.path.join(os.path.dirname(__file__), "templates"),
diff --git a/libmproxy/web/static/js/app.js b/libmproxy/web/static/js/app.js
index c095fd44..6a157b24 100644
--- a/libmproxy/web/static/js/app.js
+++ b/libmproxy/web/static/js/app.js
@@ -198,17 +198,14 @@ _.extend(_EventLogStore.prototype, EventEmitter.prototype, {
var EventLogStore = new _EventLogStore();
AppDispatcher.register(EventLogStore.handle.bind(EventLogStore));
-function _Connection(root) {"use strict";
- if (!root) {
- root = location.origin + "/api/v1";
- }
- this.root = root;
- }
-_Connection.prototype.init=function() {"use strict";
+function _Connection(url) {
+ this.url = url;
+}
+_Connection.prototype.init=function() {
this.openWebSocketConnection();
};
-_Connection.prototype.openWebSocketConnection=function() {"use strict";
- this.ws = new WebSocket(this.root.replace("http", "ws") + "/ws");
+_Connection.prototype.openWebSocketConnection=function() {
+ this.ws = new WebSocket(this.url.replace("http", "ws"));
var ws = this.ws;
ws.onopen = this.onopen.bind(this);
@@ -216,21 +213,21 @@ _Connection.prototype.openWebSocketConnection=function() {"use strict";
ws.onerror = this.onerror.bind(this);
ws.onclose = this.onclose.bind(this);
};
-_Connection.prototype.onopen=function(open) {"use strict";
+_Connection.prototype.onopen=function(open) {
console.log("onopen", this, arguments);
};
-_Connection.prototype.onmessage=function(message) {"use strict";
+_Connection.prototype.onmessage=function(message) {
//AppDispatcher.dispatchServerAction(...);
console.log("onmessage", this, arguments);
};
-_Connection.prototype.onerror=function(error) {"use strict";
+_Connection.prototype.onerror=function(error) {
console.log("onerror", this, arguments);
};
-_Connection.prototype.onclose=function(close) {"use strict";
+_Connection.prototype.onclose=function(close) {
console.log("onclose", this, arguments);
};
-var Connection = new _Connection();
+var Connection = new _Connection(location.origin + "/updates");
/** @jsx React.DOM */