fix #328
This commit is contained in:
parent
e4d6089f9a
commit
b97b1f17cf
|
@ -704,7 +704,7 @@ class FlowMaster(controller.Master):
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def handle_request(self, r):
|
def handle_request(self, r):
|
||||||
if r.flow.client_conn and r.flow.client_conn.wfile:
|
if r.flow.live:
|
||||||
app = self.apps.get(r)
|
app = self.apps.get(r)
|
||||||
if app:
|
if app:
|
||||||
err = app.serve(r, r.flow.client_conn.wfile, **{"mitmproxy.master": self})
|
err = app.serve(r, r.flow.client_conn.wfile, **{"mitmproxy.master": self})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import threading
|
||||||
from netlib import http, tcp, http_status
|
from netlib import http, tcp, http_status
|
||||||
import netlib.utils
|
import netlib.utils
|
||||||
from netlib.odict import ODict, ODictCaseless
|
from netlib.odict import ODict, ODictCaseless
|
||||||
from .primitives import KILL, ProtocolHandler, TemporaryServerChangeMixin, Flow, Error
|
from .primitives import KILL, ProtocolHandler, LiveConnection, Flow, Error
|
||||||
from ..proxy.connection import ServerConnection
|
from ..proxy.connection import ServerConnection
|
||||||
from .. import encoding, utils, controller, stateobject, proxy
|
from .. import encoding, utils, controller, stateobject, proxy
|
||||||
|
|
||||||
|
@ -543,8 +543,8 @@ class HTTPRequest(HTTPMessage):
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
if host != self.get_host() or port != self.get_port():
|
if host != self.get_host() or port != self.get_port():
|
||||||
if self.flow.change_server:
|
if self.flow.live:
|
||||||
self.flow.change_server((host, port), ssl=is_ssl)
|
self.flow.live.change_server((host, port), ssl=is_ssl)
|
||||||
else:
|
else:
|
||||||
# There's not live server connection, we're just changing the attributes here.
|
# There's not live server connection, we're just changing the attributes here.
|
||||||
self.flow.server_conn = ServerConnection((host, port),
|
self.flow.server_conn = ServerConnection((host, port),
|
||||||
|
@ -789,15 +789,15 @@ class HTTPFlow(Flow):
|
||||||
The following additional attributes are exposed:
|
The following additional attributes are exposed:
|
||||||
|
|
||||||
intercepting: Is this flow currently being intercepted?
|
intercepting: Is this flow currently being intercepted?
|
||||||
|
live: Does this flow have a live client connection?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, client_conn, server_conn, change_server=None):
|
def __init__(self, client_conn, server_conn, live=None):
|
||||||
super(HTTPFlow, self).__init__("http", client_conn, server_conn)
|
super(HTTPFlow, self).__init__("http", client_conn, server_conn, live)
|
||||||
self.request = None
|
self.request = None
|
||||||
"""@type: HTTPRequest"""
|
"""@type: HTTPRequest"""
|
||||||
self.response = None
|
self.response = None
|
||||||
"""@type: HTTPResponse"""
|
"""@type: HTTPResponse"""
|
||||||
self.change_server = change_server # Used by flow.request.set_url to change the server address
|
|
||||||
|
|
||||||
self.intercepting = False # FIXME: Should that rather be an attribute of Flow?
|
self.intercepting = False # FIXME: Should that rather be an attribute of Flow?
|
||||||
|
|
||||||
|
@ -904,7 +904,7 @@ class HttpAuthenticationError(Exception):
|
||||||
return "Proxy Authentication Required"
|
return "Proxy Authentication Required"
|
||||||
|
|
||||||
|
|
||||||
class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
|
class HTTPHandler(ProtocolHandler):
|
||||||
def __init__(self, c):
|
def __init__(self, c):
|
||||||
super(HTTPHandler, self).__init__(c)
|
super(HTTPHandler, self).__init__(c)
|
||||||
self.expected_form_in = c.config.http_form_in
|
self.expected_form_in = c.config.http_form_in
|
||||||
|
@ -943,7 +943,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
|
||||||
raise v
|
raise v
|
||||||
|
|
||||||
def handle_flow(self):
|
def handle_flow(self):
|
||||||
flow = HTTPFlow(self.c.client_conn, self.c.server_conn, self.change_server)
|
flow = HTTPFlow(self.c.client_conn, self.c.server_conn, self.live)
|
||||||
try:
|
try:
|
||||||
req = HTTPRequest.from_stream(self.c.client_conn.rfile,
|
req = HTTPRequest.from_stream(self.c.client_conn.rfile,
|
||||||
body_size_limit=self.c.config.body_size_limit)
|
body_size_limit=self.c.config.body_size_limit)
|
||||||
|
@ -1038,7 +1038,8 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
|
||||||
|
|
||||||
# If the user has changed the target server on this connection,
|
# If the user has changed the target server on this connection,
|
||||||
# restore the original target server
|
# restore the original target server
|
||||||
self.restore_server()
|
flow.live.restore_server()
|
||||||
|
flow.live = None
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except (HttpAuthenticationError, http.HttpError, proxy.ProxyError, tcp.NetLibError), e:
|
except (HttpAuthenticationError, http.HttpError, proxy.ProxyError, tcp.NetLibError), e:
|
||||||
|
|
|
@ -71,12 +71,14 @@ class Error(stateobject.SimpleStateObject):
|
||||||
|
|
||||||
|
|
||||||
class Flow(stateobject.SimpleStateObject, BackreferenceMixin):
|
class Flow(stateobject.SimpleStateObject, BackreferenceMixin):
|
||||||
def __init__(self, conntype, client_conn, server_conn):
|
def __init__(self, conntype, client_conn, server_conn, live=None):
|
||||||
self.conntype = conntype
|
self.conntype = conntype
|
||||||
self.client_conn = client_conn
|
self.client_conn = client_conn
|
||||||
"""@type: ClientConnection"""
|
"""@type: ClientConnection"""
|
||||||
self.server_conn = server_conn
|
self.server_conn = server_conn
|
||||||
"""@type: ServerConnection"""
|
"""@type: ServerConnection"""
|
||||||
|
self.live = live # Used by flow.request.set_url to change the server address
|
||||||
|
"""@type: LiveConnection"""
|
||||||
|
|
||||||
self.error = None
|
self.error = None
|
||||||
"""@type: Error"""
|
"""@type: Error"""
|
||||||
|
@ -140,6 +142,8 @@ class ProtocolHandler(object):
|
||||||
def __init__(self, c):
|
def __init__(self, c):
|
||||||
self.c = c
|
self.c = c
|
||||||
"""@type: libmproxy.proxy.server.ConnectionHandler"""
|
"""@type: libmproxy.proxy.server.ConnectionHandler"""
|
||||||
|
self.live = LiveConnection(c)
|
||||||
|
"""@type: LiveConnection"""
|
||||||
|
|
||||||
def handle_messages(self):
|
def handle_messages(self):
|
||||||
"""
|
"""
|
||||||
|
@ -164,46 +168,50 @@ class ProtocolHandler(object):
|
||||||
raise error # pragma: nocover
|
raise error # pragma: nocover
|
||||||
|
|
||||||
|
|
||||||
class TemporaryServerChangeMixin(object):
|
class LiveConnection(object):
|
||||||
"""
|
"""
|
||||||
This mixin allows safe modification of the target server,
|
This facade allows protocol handlers to interface with a live connection,
|
||||||
without any need to expose the ConnectionHandler to the Flow.
|
without requiring the expose the ConnectionHandler.
|
||||||
"""
|
"""
|
||||||
def change_server(self, address, ssl):
|
def __init__(self, c):
|
||||||
|
self._c = c
|
||||||
|
"""@type: libmproxy.proxy.server.ConnectionHandler"""
|
||||||
|
|
||||||
|
def change_server(self, address, ssl, persistent_change=False):
|
||||||
address = netlib.tcp.Address.wrap(address)
|
address = netlib.tcp.Address.wrap(address)
|
||||||
if address == self.c.server_conn.address():
|
if address != self._c.server_conn.address:
|
||||||
return
|
|
||||||
priority = AddressPriority.MANUALLY_CHANGED
|
|
||||||
|
|
||||||
self.c.log("Temporarily change server connection: %s:%s -> %s:%s" % (
|
self._c.log("Change server connection: %s:%s -> %s:%s" % (
|
||||||
self.c.server_conn.address.host,
|
self._c.server_conn.address.host,
|
||||||
self.c.server_conn.address.port,
|
self._c.server_conn.address.port,
|
||||||
address.host,
|
address.host,
|
||||||
address.port
|
address.port
|
||||||
), "debug")
|
), "debug")
|
||||||
|
|
||||||
if not hasattr(self, "_backup_server_conn"):
|
if not hasattr(self, "_backup_server_conn"):
|
||||||
self._backup_server_conn = self.c.server_conn
|
self._backup_server_conn = self._c.server_conn
|
||||||
self.c.server_conn = None
|
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.del_server_connection()
|
||||||
|
|
||||||
self.c.set_server_address(address, priority)
|
self._c.set_server_address(address, AddressPriority.MANUALLY_CHANGED)
|
||||||
self.c.establish_server_connection(ask=False)
|
self._c.establish_server_connection(ask=False)
|
||||||
if ssl:
|
if ssl:
|
||||||
self.c.establish_ssl(server=True)
|
self._c.establish_ssl(server=True)
|
||||||
|
if hasattr(self, "_backup_server_conn") and persistent_change:
|
||||||
|
del self._backup_server_conn
|
||||||
|
|
||||||
def restore_server(self):
|
def restore_server(self):
|
||||||
if not hasattr(self, "_backup_server_conn"):
|
if not hasattr(self, "_backup_server_conn"):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.c.log("Restore original server connection: %s:%s -> %s:%s" % (
|
self._c.log("Restore original server connection: %s:%s -> %s:%s" % (
|
||||||
self.c.server_conn.address.host,
|
self._c.server_conn.address.host,
|
||||||
self.c.server_conn.address.port,
|
self._c.server_conn.address.port,
|
||||||
self._backup_server_conn.address.host,
|
self._backup_server_conn.address.host,
|
||||||
self._backup_server_conn.address.port
|
self._backup_server_conn.address.port
|
||||||
), "debug")
|
), "debug")
|
||||||
|
|
||||||
self.c.del_server_connection()
|
self._c.del_server_connection()
|
||||||
self.c.server_conn = self._backup_server_conn
|
self._c.server_conn = self._backup_server_conn
|
||||||
del self._backup_server_conn
|
del self._backup_server_conn
|
|
@ -338,9 +338,9 @@ class MasterRedirectRequest(tservers.TestMaster):
|
||||||
|
|
||||||
request.set_url(new)
|
request.set_url(new)
|
||||||
request.set_url(new)
|
request.set_url(new)
|
||||||
request.flow.change_server(("127.0.0.1", self.redirect_port), False)
|
request.flow.live.change_server(("127.0.0.1", self.redirect_port), False)
|
||||||
request.set_url(url)
|
request.set_url(url)
|
||||||
tutils.raises("SSL handshake error", request.flow.change_server, ("127.0.0.1", self.redirect_port), True)
|
tutils.raises("SSL handshake error", request.flow.live.change_server, ("127.0.0.1", self.redirect_port), True)
|
||||||
request.set_url(new)
|
request.set_url(new)
|
||||||
request.set_url(url)
|
request.set_url(url)
|
||||||
request.set_url(new)
|
request.set_url(new)
|
||||||
|
|
Loading…
Reference in New Issue