app/site-content/proposals/2009/08/07/proxy.py
changeset 20 327b3f0b73bb
equal deleted inserted replaced
19:0c9bdcfac9f7 20:327b3f0b73bb
       
     1 # urllib2 opener to connection through a proxy using the CONNECT method, (useful for SSL)
       
     2 # tested with python 2.4
       
     3 
       
     4 import urllib2
       
     5 import urllib
       
     6 import httplib
       
     7 import socket
       
     8 
       
     9 
       
    10 class ProxyHTTPConnection(httplib.HTTPConnection):
       
    11 
       
    12     _ports = {'http' : 80, 'https' : 443}
       
    13 
       
    14 
       
    15     def request(self, method, url, body=None, headers={}):
       
    16         #request is called before connect, so can interpret url and get
       
    17         #real host/port to be used to make CONNECT request to proxy
       
    18         proto, rest = urllib.splittype(url)
       
    19         if proto is None:
       
    20             raise ValueError, "unknown URL type: %s" % url
       
    21         #get host
       
    22         host, rest = urllib.splithost(rest)
       
    23         #try to get port
       
    24         host, port = urllib.splitport(host)
       
    25         #if port is not defined try to get from proto
       
    26         if port is None:
       
    27             try:
       
    28                 port = self._ports[proto]
       
    29             except KeyError:
       
    30                 raise ValueError, "unknown protocol for: %s" % url
       
    31         self._real_host = host
       
    32         self._real_port = port
       
    33         httplib.HTTPConnection.request(self, method, url, body, headers)
       
    34         
       
    35 
       
    36     def connect(self):
       
    37         httplib.HTTPConnection.connect(self)
       
    38         #send proxy CONNECT request
       
    39         self.send("CONNECT %s:%d HTTP/1.0\r\n\r\n" % (self._real_host, self._real_port))
       
    40         #expect a HTTP/1.0 200 Connection established
       
    41         response = self.response_class(self.sock, strict=self.strict, method=self._method)
       
    42         (version, code, message) = response._read_status()
       
    43         #probably here we can handle auth requests...
       
    44         if code != 200:
       
    45             #proxy returned and error, abort connection, and raise exception
       
    46             self.close()
       
    47             raise socket.error, "Proxy connection failed: %d %s" % (code, message.strip())
       
    48         #eat up header block from proxy....
       
    49         while True:
       
    50             #should not use directly fp probablu
       
    51             line = response.fp.readline()
       
    52             if line == '\r\n': break
       
    53 
       
    54 
       
    55 class ProxyHTTPSConnection(ProxyHTTPConnection):
       
    56     
       
    57     default_port = 443
       
    58 
       
    59     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
       
    60         ProxyHTTPConnection.__init__(self, host, port)
       
    61         self.key_file = key_file
       
    62         self.cert_file = cert_file
       
    63     
       
    64     def connect(self):
       
    65         ProxyHTTPConnection.connect(self)
       
    66         #make the sock ssl-aware
       
    67         ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
       
    68         self.sock = httplib.FakeSocket(self.sock, ssl)
       
    69         
       
    70                                        
       
    71 class ConnectHTTPHandler(urllib2.HTTPHandler):
       
    72 
       
    73     def do_open(self, http_class, req):
       
    74         return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
       
    75 
       
    76 
       
    77 class ConnectHTTPSHandler(urllib2.HTTPSHandler):
       
    78 
       
    79     def do_open(self, http_class, req):
       
    80         return urllib2.HTTPSHandler.do_open(self, ProxyHTTPSConnection, req)
       
    81 
       
    82 
       
    83 if __name__ == '__main__':
       
    84     
       
    85     import sys
       
    86     
       
    87     opener = urllib2.build_opener(ConnectHTTPHandler, ConnectHTTPSHandler)
       
    88     urllib2.install_opener(opener)
       
    89     req = urllib2.Request(url='http://google.com')
       
    90     req.set_proxy('10.101.1.1:80', 'http')
       
    91     f = urllib2.urlopen(req)
       
    92     print f.read()
       
    93