diff options
| -rw-r--r-- | libmproxy/flow.py | 24 | ||||
| -rw-r--r-- | libmproxy/protocol/primitives.py | 43 | ||||
| -rw-r--r-- | libmproxy/web/__init__.py | 6 | ||||
| -rw-r--r-- | libmproxy/web/app.py | 22 | ||||
| -rw-r--r-- | libmproxy/web/static/js/app.js | 25 | ||||
| -rw-r--r-- | web/src/js/connection.js | 25 | 
6 files changed, 85 insertions, 60 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 */ diff --git a/web/src/js/connection.js b/web/src/js/connection.js index 3911d3f2..e752e2fe 100644 --- a/web/src/js/connection.js +++ b/web/src/js/connection.js @@ -1,14 +1,11 @@ -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); @@ -16,18 +13,18 @@ _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"); | 
