#!/usr/bin/python -t import asynchat, asyncore, socket, httplib, urlparse import pwd, os, sys, logging, logging.handlers import string try: import cStringIO as StringIO except ImportError: import StringIO endpoints = { {'host':'10.1.0.1', 'port':'8080', 'speed':220, 'name':'Yves Proxy'}, {'host':'10.3.0.99', 'port':'8080', 'speed':340, 'name':'Thomas Proxy'}, } class HTTPResponseProducer(object): def __init__(self, resp, amt=512): self.resp = resp self.amt = amt def more(self): return self.resp.read(self.amt) class HTTPChannel(asynchat.async_chat): def __init__(self, server, sock, addr): asynchat.async_chat.__init__(self, sock) self.server = server self.set_terminator("\r\n\r\n") self.request = None self.data = StringIO.StringIO() self.shutdown = 0 def collect_incoming_data(self, data): self.data.write(data) if self.data.tell() > 16384: self.close_when_done() def found_terminator(self): if not self.request: # parse http header self.data.seek(0) self.request = string.split(self.data.readline(), None, 2) if len(self.request) != 3: # badly formed request; just shut down self.close_when_done() else: self.server.handle_request(self, self.request[0], self.request[1]) self.close_when_done() else: pass # ignore body data, for now class HTTPProxyServer(asyncore.dispatcher): def __init__(self): asyncore.dispatcher.__init__(self) self.port = 8080 self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(("", 8080)) self.listen(5) def handle_accept(self): conn, addr = self.accept() HTTPChannel(self, conn, addr) def handle_request(self, channel, method, path): url = urlparse.urlparse(path) print method, path if method != "GET": return self._do_standard_proxy(channel, method, url) #check for content-length header with a HEAD request conn = httplib.HTTPConnection(url.hostname, url.port or 80) conn.request("HEAD", url.path) resp = conn.getresponse() content_length = filter(lambda it: it[0] == "content-length", resp.getheaders()) if len( content_length ) == 0: return self._do_standard_proxy(channel, method, url) else: content_length = content_length[0][1] print "Content-Length: %s" % (content_length) return self._do_standard_proxy(channel, method, url) #print "do some magic for " +str(url) #channel.push("HTTP/1.0 200 OK\r\nX-Proxy: Magicproxy (request handled in boost mode)\r\n") #channel.close_when_done() def _do_standard_proxy(self, channel, method, url): conn = httplib.HTTPConnection(url.hostname, url.port or 80) conn.request(method, url.path) resp = conn.getresponse() channel.push("HTTP/1.0 200 OK\r\nX-Proxy: Magicproxy (request handled in standard mode)\r\n") channel.push( "\r\n".join(map(lambda k: "%s: %s" % (k[0],k[1]), resp.getheaders())) ) channel.push("\r\n\r\n") channel.push_with_producer( HTTPResponseProducer(resp) ) if __name__ == "__main__": proxy = HTTPProxyServer() asyncore.loop()