fix display of urls in upstream mode, refs #308

This commit is contained in:
Maximilian Hils 2014-08-08 17:49:02 +02:00
parent de05484d9d
commit 4d2109ef92
4 changed files with 24 additions and 3 deletions

View File

@ -461,6 +461,11 @@ class HTTPRequest(HTTPMessage):
if self.host: if self.host:
host = self.host host = self.host
else: else:
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 = self.flow.server_conn.address.host
host = host.encode("idna") host = host.encode("idna")
return host return host
@ -479,6 +484,9 @@ class HTTPRequest(HTTPMessage):
""" """
if self.port: if self.port:
return 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 return self.flow.server_conn.address.port
def get_url(self, hostheader=False): def get_url(self, hostheader=False):
@ -974,11 +982,16 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
return False return False
if flow.request.form_in == "authority" and flow.response.code == 200: if flow.request.form_in == "authority" and flow.response.code == 200:
self.ssl_upgrade()
# TODO: Eventually add headers (space/usefulness tradeoff) # 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", self.c.server_conn.state.append(("http", {"state": "connect",
"host": flow.request.host, "host": flow.request.host,
"port": flow.request.port})) "port": flow.request.port}))
self.ssl_upgrade()
# 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

View File

@ -138,7 +138,7 @@ class ServerConnection(tcp.TCPClient, stateobject.SimpleStateObject):
self.convert_to_ssl(cert=clientcert, sni=sni) self.convert_to_ssl(cert=clientcert, sni=sni)
self.timestamp_ssl_setup = utils.timestamp() self.timestamp_ssl_setup = utils.timestamp()
except tcp.NetLibError, v: except tcp.NetLibError, v:
raise ProxyError(400, str(v)) raise ProxyError(400, repr(v))
def finish(self): def finish(self):
tcp.TCPClient.finish(self) tcp.TCPClient.finish(self)

View File

@ -141,6 +141,12 @@ class TestProxyChainingSSL(tservers.HTTPChainProxyTest):
finally: finally:
self.chain[0].tmaster.handle_request = _handle_request 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): class TestProxyChainingSSLReconnect(tservers.HTTPChainProxyTest):
ssl = True ssl = True

View File

@ -33,6 +33,7 @@ def tclient_conn():
def tserver_conn(): def tserver_conn():
c = ServerConnection._from_state(dict( c = ServerConnection._from_state(dict(
address=dict(address=("address", 22), use_ipv6=True), address=dict(address=("address", 22), use_ipv6=True),
state=[],
source_address=dict(address=("address", 22), use_ipv6=True), source_address=dict(address=("address", 22), use_ipv6=True),
cert=None 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()) cert = certutils.SSLCert.from_der(file(test_data.path("data/dercert"), "rb").read())
f.server_conn = ServerConnection._from_state(dict( f.server_conn = ServerConnection._from_state(dict(
address=dict(address=("address", 22), use_ipv6=True), address=dict(address=("address", 22), use_ipv6=True),
state=[],
source_address=None, source_address=None,
cert=cert.to_pem())) cert=cert.to_pem()))
f.response = http.HTTPResponse((1, 1), 200, "OK", headers, content, time(), time()) f.response = http.HTTPResponse((1, 1), 200, "OK", headers, content, time(), time())