CONNECT through proxy mode for pathoc

Also, use this to unit test the pathod CONNECT implementation.
This commit is contained in:
Aldo Cortesi 2013-01-05 20:29:46 +13:00
parent c744ef2dcb
commit 5493925ea0
4 changed files with 45 additions and 7 deletions

View File

@ -15,8 +15,23 @@ class Pathoc(tcp.TCPClient):
)
self.ssl, self.sni = ssl, sni
def connect(self):
def http_connect(self, connect_to, wfile, rfile):
wfile.write(
'CONNECT %s:%s HTTP/1.1\r\n'%tuple(connect_to) +
'\r\n'
)
wfile.flush()
rfile.readline()
headers = http.read_headers(self.rfile)
def connect(self, connect_to=None):
"""
connect_to: A (host, port) tuple, which will be connected to with an
HTTP CONNECT request.
"""
tcp.TCPClient.connect(self)
if connect_to:
self.http_connect(connect_to, self.wfile, self.rfile)
if self.ssl:
try:
self.convert_to_ssl(sni=self.sni)

19
pathoc
View File

@ -17,6 +17,11 @@ if __name__ == "__main__":
sys.exit(0)
parser = argparse.ArgumentParser(description='A perverse HTTP client.', parents=[preparser])
parser.add_argument(
"-c", dest="connect_to", type=str, default=False,
metavar = "HOST:PORT",
help="Issue an HTTP CONNECT to connect to the specified host."
)
parser.add_argument(
"-i", dest="sni", type=str, default=False,
help="SSL Server Name Indication"
@ -94,11 +99,23 @@ if __name__ == "__main__":
except ValueError:
parser.error("Invalid return code specification: %s"%args.ignorecodes)
if args.connect_to:
parts = args.connect_to.split(":")
if len(parts) != 2:
parser.error("Invalid CONNECT specification: %s"%args.connect_to)
try:
parts[1] = int(parts[1])
except ValueError:
parser.error("Invalid CONNECT specification: %s"%args.connect_to)
connect_to = parts
else:
connect_to = None
try:
for i in range(args.repeat):
p = pathoc.Pathoc(args.host, port, args.ssl, args.sni)
try:
p.connect()
p.connect(connect_to)
except tcp.NetLibError, v:
print >> sys.stderr, str(v)
sys.exit(1)

View File

@ -150,6 +150,12 @@ class CommonTests(tutils.DaemonTests):
class TestDaemon(CommonTests):
ssl = False
def test_connect(self):
v = self.pathoc(r"get:'http://foo.com/p/202':da", connect_to=("localhost", self.d.port), ssl=True)
assert v[1] == 202
def test_connect_err(self):
tutils.raises(http.HttpError, self.pathoc, r"get:'http://foo.com/p/202':da", connect_to=("localhost", self.d.port))
class TestDaemonSSL(CommonTests):

View File

@ -44,11 +44,11 @@ class DaemonTests:
def get(self, spec):
return requests.get(self.d.p(spec), verify=False)
def pathoc(self, spec, timeout=None):
c = pathoc.Pathoc("localhost", self.d.port)
c.connect()
if self.ssl:
c.convert_to_ssl()
def pathoc(self, spec, timeout=None, connect_to=None, ssl=None):
if ssl is None:
ssl = self.ssl
c = pathoc.Pathoc("localhost", self.d.port, ssl=ssl)
c.connect(connect_to)
if timeout:
c.settimeout(timeout)
return c.request(spec)