|
| 1 | +''' |
| 2 | +Created on Jan 11, 2012 |
| 3 | +
|
| 4 | +@author: philipkershaw |
| 5 | +''' |
| 6 | +import socket |
| 7 | +from httplib import HTTPConnection as _HTTPConnection |
| 8 | +from httplib import HTTPException |
| 9 | + |
| 10 | +# maximal line length when calling readline(). |
| 11 | +_MAXLINE = 65536 |
| 12 | + |
| 13 | +class LineTooLong(HTTPException): |
| 14 | + def __init__(self, line_type): |
| 15 | + HTTPException.__init__(self, "got more than %d bytes when reading %s" |
| 16 | + % (_MAXLINE, line_type)) |
| 17 | + |
| 18 | + |
| 19 | +class HTTPConnection(_HTTPConnection): |
| 20 | + NDG_HTTPSCLIENT = True |
| 21 | + |
| 22 | + def __init__(self, *arg, **kwarg): |
| 23 | + self._tunnel_host = None |
| 24 | + self._tunnel_port = None |
| 25 | + self._tunnel_headers = {} |
| 26 | + |
| 27 | + _HTTPConnection.__init__(self, *arg, **kwarg) |
| 28 | + |
| 29 | + def set_tunnel(self, host, port=None, headers=None): |
| 30 | + """ Sets up the host and the port for the HTTP CONNECT Tunnelling. |
| 31 | +
|
| 32 | + The headers argument should be a mapping of extra HTTP headers |
| 33 | + to send with the CONNECT request. |
| 34 | + """ |
| 35 | + self._tunnel_host = host |
| 36 | + self._tunnel_port = port |
| 37 | + if headers: |
| 38 | + self._tunnel_headers = headers |
| 39 | + else: |
| 40 | + self._tunnel_headers.clear() |
| 41 | + |
| 42 | + def _tunnel(self): |
| 43 | + self._set_hostport(self._tunnel_host, self._tunnel_port) |
| 44 | + self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self.host, self.port)) |
| 45 | + for header, value in self._tunnel_headers.iteritems(): |
| 46 | + self.send("%s: %s\r\n" % (header, value)) |
| 47 | + self.send("\r\n") |
| 48 | + response = self.response_class(self.sock, strict = self.strict, |
| 49 | + method = self._method) |
| 50 | + (version, code, message) = response._read_status() |
| 51 | + |
| 52 | + if code != 200: |
| 53 | + self.close() |
| 54 | + raise socket.error("Tunnel connection failed: %d %s" % (code, |
| 55 | + message.strip())) |
| 56 | + while True: |
| 57 | + line = response.fp.readline(_MAXLINE + 1) |
| 58 | + if len(line) > _MAXLINE: |
| 59 | + raise LineTooLong("header line") |
| 60 | + if line == '\r\n': break |
| 61 | + |
| 62 | + def connect(self): |
| 63 | + """Connect to the host and port specified in __init__.""" |
| 64 | + _HTTPConnection.connect(self) |
| 65 | + |
| 66 | + if self._tunnel_host: |
| 67 | + self._tunnel() |
0 commit comments