This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for http proxy authentication
- Loading branch information
Showing
2 changed files
with
127 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -205,6 +205,10 @@ def test_https_request_via_no_proxy_star(self): | |
|
||
@patch.dict(os.environ, {"http_proxy": "proxy.com:8888", "no_proxy": "unused.com"}) | ||
def test_http_request_via_proxy(self): | ||
""" | ||
Tests that requests can be made through a proxy | ||
This use transparent proxy. | ||
""" | ||
agent = ProxyAgent(self.reactor, use_proxy=True) | ||
|
||
self.reactor.lookups["proxy.com"] = "1.2.3.5" | ||
|
@@ -229,6 +233,7 @@ def test_http_request_via_proxy(self): | |
self.assertEqual(len(http_server.requests), 1) | ||
|
||
request = http_server.requests[0] | ||
|
||
self.assertEqual(request.method, b"GET") | ||
self.assertEqual(request.path, b"http://test.com") | ||
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"test.com"]) | ||
|
@@ -241,6 +246,104 @@ def test_http_request_via_proxy(self): | |
body = self.successResultOf(treq.content(resp)) | ||
self.assertEqual(body, b"result") | ||
|
||
@patch.dict( | ||
os.environ, | ||
{"http_proxy": "bob:[email protected]:8888", "no_proxy": "unused.com"}, | ||
) | ||
def test_http_request_via_proxy_with_auth(self): | ||
""" | ||
Tests that authenticated requests can be made through a proxy | ||
This use a proxy tunnel via CONNECT method similar to https. | ||
""" | ||
agent = ProxyAgent(self.reactor, use_proxy=True) | ||
|
||
self.reactor.lookups["proxy.com"] = "1.2.3.5" | ||
d = agent.request(b"GET", b"http://test.com/abc") | ||
|
||
# there should be a pending TCP connection | ||
clients = self.reactor.tcpClients | ||
self.assertEqual(len(clients), 1) | ||
(host, port, client_factory, _timeout, _bindAddress) = clients[0] | ||
self.assertEqual(host, "1.2.3.5") | ||
self.assertEqual(port, 8888) | ||
|
||
# make a test HTTP server, and wire up the client | ||
proxy_server = self._make_connection( | ||
client_factory, _get_test_protocol_factory() | ||
) | ||
|
||
# fish the transports back out so that we can do the old switcheroo | ||
s2c_transport = proxy_server.transport | ||
client_protocol = s2c_transport.other | ||
c2s_transport = client_protocol.transport | ||
|
||
# the FakeTransport is async, so we need to pump the reactor | ||
self.reactor.advance(0) | ||
|
||
# now there should be a pending CONNECT request | ||
self.assertEqual(len(proxy_server.requests), 1) | ||
|
||
request = proxy_server.requests[0] | ||
self.assertEqual(request.method, b"CONNECT") | ||
self.assertEqual(request.path, b"test.com:80") | ||
|
||
# Check whether auth credentials have been supplied to the proxy | ||
proxy_auth_header_values = request.requestHeaders.getRawHeaders( | ||
b"Proxy-Authorization" | ||
) | ||
# Compute the correct header value for Proxy-Authorization | ||
encoded_credentials = base64.b64encode(b"bob:pinkponies") | ||
expected_header_value = b"Basic " + encoded_credentials | ||
|
||
# Validate the header's value | ||
self.assertIn(expected_header_value, proxy_auth_header_values) | ||
|
||
# tell the proxy server not to close the connection | ||
proxy_server.persistent = True | ||
|
||
# this just stops the http Request trying to do a chunked response | ||
# request.setHeader(b"Content-Length", b"0") | ||
request.finish() | ||
|
||
''' | ||
here need to wrap the http request, but not with ssl | ||
# now we can replace the proxy channel with a new, SSL-wrapped HTTP channel | ||
ssl_factory = _wrap_server_factory_for_tls(_get_test_protocol_factory()) | ||
ssl_protocol = ssl_factory.buildProtocol(None) | ||
http_server = ssl_protocol.wrappedProtocol | ||
ssl_protocol.makeConnection( | ||
FakeTransport(client_protocol, self.reactor, ssl_protocol) | ||
) | ||
c2s_transport.other = ssl_protocol | ||
self.reactor.advance(0) | ||
# now there should be a pending request | ||
self.assertEqual(len(http_server.requests), 1) | ||
request = http_server.requests[0] | ||
self.assertEqual(request.method, b"GET") | ||
self.assertEqual(request.path, b"/abc") | ||
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"test.com"]) | ||
# Check that the destination server DID NOT receive proxy credentials | ||
proxy_auth_header_values = request.requestHeaders.getRawHeaders( | ||
b"Proxy-Authorization" | ||
) | ||
self.assertIsNone(proxy_auth_header_values) | ||
request.write(b"result") | ||
request.finish() | ||
self.reactor.advance(0) | ||
resp = self.successResultOf(d) | ||
body = self.successResultOf(treq.content(resp)) | ||
self.assertEqual(body, b"result") | ||
''' | ||
|
||
@patch.dict(os.environ, {"https_proxy": "proxy.com", "no_proxy": "unused.com"}) | ||
def test_https_request_via_proxy(self): | ||
"""Tests that TLS-encrypted requests can be made through a proxy""" | ||
|