Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import BaseHTTPServer, select, socket, SocketServer, urlparse
- #Http server + threading mixin
- class ThreadingHTTPServer (SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): pass
- class HTTPProxy (BaseHTTPServer.BaseHTTPRequestHandler):
- rbufsize = 0 #Unbuffered file reader
- #Utility function to give a chance to modify self.headers before proxying
- def modifyOutboundHeaders(self):
- #Can add or modify outbound headers here, setting cookies or whatever
- return
- #Utility to modify output data before proxying
- def modifyOutboundData(self,data):
- return data
- #utility function to modify response data(headers and body)
- def modifyResponse(self, data):
- #Modify data as fit
- return data
- #Just a little function to handle output, didn't use it much but thought I might
- def trace(self, msg):
- print msg
- #Performs the actual proxy connection
- def connect(self, location, soc):
- #Parse connection information
- i = location.find(':')
- if i >= 0:
- host = location[:i]
- port = int(location[i+1:])
- else:
- host = location
- port = 80
- self.trace("Connecting to %s:%d" % (host,port))
- #Try to connect
- try:
- soc.connect((host,port))
- except socket.error, arg:
- try: msg = arg[1]
- except: msg = arg
- self.send_error(503, msg)
- return False
- return True
- #Reads data from either proxied connection or client and redirects it to the other
- def redirectData(self, soc, idleCount=50):
- loops = 0 #Tracks loops without reading; if we idle too long kill the connection
- while True:
- loops += 1
- (reads,_,errs) = select.select([self.connection, soc], [], [self.connection, soc])
- #Leave loop once we get an error as there is nothing left
- if errs: break
- #Read the data if anything and send it to the other source
- if reads:
- for i in reads:
- data = i.recv(8192)
- if data:
- loops = 0
- if i is soc:
- data = self.modifyResponse(data)
- self.connection.send(data)
- else:
- data = self.modifyOutboundData(data)
- soc.send(data)
- if loops >= idleCount: break
- def do_CONNECT(self):
- soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- try:
- if self.connect(self.path, soc):
- #Successful connection
- self.trace("Connected.")
- self.wfile.write(self.protocol_version + " 200 Connection established\r\n")
- self.wfile.write("\r\n")
- self.redirectData(soc, 300)
- finally: soc.close()
- def do_GET(self):
- (proto, host, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
- if proto != 'http' or not host:
- self.send_error(500, "No support for HTTPS or no host provided.")
- return
- soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- try:
- if self.connect(host, soc):
- soc.send("%s %s %s\r\n" % (self.command,urlparse.urlunparse(('', '', path, params, query, '')),self.request_version))
- #Don't bother dealing with keep-alives
- self.headers['Connection'] = 'close'
- self.modifyOutboundHeaders()
- #Send the headers to socket
- for key_val in self.headers.items():
- soc.send("%s: %s\r\n" % key_val)
- soc.send("\r\n")
- self.redirectData(soc)
- finally:
- soc.close()
- self.connection.close()
- #GET is generic enough that it handles everything
- do_POST = do_GET
- do_HEAD = do_GET
- do_PUT = do_GET
- do_DELETE = do_GET
- if __name__ == '__main__':
- #Run the server, default is port 8000 but argv[1] is read to determine port
- BaseHTTPServer.test(HTTPProxy, ThreadingHTTPServer)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement