aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2014-08-08 17:49:02 +0200
committerMaximilian Hils <git@maximilianhils.com>2014-08-08 17:49:02 +0200
commit4d2109ef92d59e48c08279e3b59b7cc8385e02df (patch)
tree073435551d0340f85e19384056b5f5acd2909146
parentde05484d9d08a4bc40c17c673b18bc2e0f910fff (diff)
downloadmitmproxy-4d2109ef92d59e48c08279e3b59b7cc8385e02df.tar.gz
mitmproxy-4d2109ef92d59e48c08279e3b59b7cc8385e02df.tar.bz2
mitmproxy-4d2109ef92d59e48c08279e3b59b7cc8385e02df.zip
fix display of urls in upstream mode, refs #308
-rw-r--r--libmproxy/protocol/http.py17
-rw-r--r--libmproxy/proxy/connection.py2
-rw-r--r--test/test_protocol_http.py6
-rw-r--r--test/tutils.py2
4 files changed, 24 insertions, 3 deletions
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index e4f994c9..7c4d9cbb 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -461,7 +461,12 @@ class HTTPRequest(HTTPMessage):
if self.host:
host = self.host
else:
- host = self.flow.server_conn.address.host
+ for s in self.flow.server_conn.state:
+ if s[0] == "http" and s[1].get("state") == "connect":
+ host = s[1]["host"]
+ break
+ if not host:
+ host = self.flow.server_conn.address.host
host = host.encode("idna")
return host
@@ -479,6 +484,9 @@ class HTTPRequest(HTTPMessage):
"""
if self.port:
return self.port
+ for s in self.flow.server_conn.state:
+ if s[0] == "http" and s[1].get("state") == "connect":
+ return s[1]["port"]
return self.flow.server_conn.address.port
def get_url(self, hostheader=False):
@@ -974,11 +982,16 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
return False
if flow.request.form_in == "authority" and flow.response.code == 200:
- self.ssl_upgrade()
# TODO: Eventually add headers (space/usefulness tradeoff)
+ # Make sure to add state info before the actual upgrade happens.
+ # During the upgrade, we may receive an SNI indication from the client,
+ # which resets the upstream connection. If this is the case, we must
+ # already re-issue the CONNECT request at this point.
self.c.server_conn.state.append(("http", {"state": "connect",
"host": flow.request.host,
"port": flow.request.port}))
+ self.ssl_upgrade()
+
# If the user has changed the target server on this connection,
# restore the original target server
diff --git a/libmproxy/proxy/connection.py b/libmproxy/proxy/connection.py
index 38436233..a19e3e71 100644
--- a/libmproxy/proxy/connection.py
+++ b/libmproxy/proxy/connection.py
@@ -138,7 +138,7 @@ class ServerConnection(tcp.TCPClient, stateobject.SimpleStateObject):
self.convert_to_ssl(cert=clientcert, sni=sni)
self.timestamp_ssl_setup = utils.timestamp()
except tcp.NetLibError, v:
- raise ProxyError(400, str(v))
+ raise ProxyError(400, repr(v))
def finish(self):
tcp.TCPClient.finish(self)
diff --git a/test/test_protocol_http.py b/test/test_protocol_http.py
index 451b7b5d..3b922c06 100644
--- a/test/test_protocol_http.py
+++ b/test/test_protocol_http.py
@@ -141,6 +141,12 @@ class TestProxyChainingSSL(tservers.HTTPChainProxyTest):
finally:
self.chain[0].tmaster.handle_request = _handle_request
+ def test_sni(self):
+ p = self.pathoc(sni="foo.com")
+ req = p.request("get:'/p/418:b\"content\"'")
+ assert req.content == "content"
+ assert req.status_code == 418
+
class TestProxyChainingSSLReconnect(tservers.HTTPChainProxyTest):
ssl = True
diff --git a/test/tutils.py b/test/tutils.py
index c527a64a..dc049adb 100644
--- a/test/tutils.py
+++ b/test/tutils.py
@@ -33,6 +33,7 @@ def tclient_conn():
def tserver_conn():
c = ServerConnection._from_state(dict(
address=dict(address=("address", 22), use_ipv6=True),
+ state=[],
source_address=dict(address=("address", 22), use_ipv6=True),
cert=None
))
@@ -72,6 +73,7 @@ def tresp(req=None, content="message"):
cert = certutils.SSLCert.from_der(file(test_data.path("data/dercert"), "rb").read())
f.server_conn = ServerConnection._from_state(dict(
address=dict(address=("address", 22), use_ipv6=True),
+ state=[],
source_address=None,
cert=cert.to_pem()))
f.response = http.HTTPResponse((1, 1), 200, "OK", headers, content, time(), time())