diff options
author | Jeff Muizelaar <jmuizelaar@mozilla.com> | 2009-12-28 16:54:25 -0500 |
---|---|---|
committer | Jeff Muizelaar <jmuizelaar@mozilla.com> | 2009-12-28 16:54:25 -0500 |
commit | e9da74b5a91129bd94d28545f7d586676aed6117 (patch) | |
tree | bbcfd1970a7f8d6cccf56e52b0998b5703d3359e |
Initial commit
-rw-r--r-- | LICENSE.txt | 22 | ||||
-rwxr-xr-x | TinyHTTPProxy.py | 133 |
2 files changed, 155 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..fbf57da --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2001 SUZUKI Hisao + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/TinyHTTPProxy.py b/TinyHTTPProxy.py new file mode 100755 index 0000000..3d82b2d --- /dev/null +++ b/TinyHTTPProxy.py @@ -0,0 +1,133 @@ +#!/bin/sh - +"exec" "python" "-O" "$0" "$@" + +__doc__ = """Tiny HTTP Proxy. + +This module implements GET, HEAD, POST, PUT and DELETE methods +on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT +method is also implemented experimentally, but has not been +tested yet. + +Any help will be greatly appreciated. SUZUKI Hisao +""" + +__version__ = "0.2.1" + +import BaseHTTPServer, select, socket, SocketServer, urlparse + +class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler): + __base = BaseHTTPServer.BaseHTTPRequestHandler + __base_handle = __base.handle + + server_version = "TinyHTTPProxy/" + __version__ + rbufsize = 0 # self.rfile Be unbuffered + + def handle(self): + (ip, port) = self.client_address + if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients: + self.raw_requestline = self.rfile.readline() + if self.parse_request(): self.send_error(403) + else: + self.__base_handle() + + def _connect_to(self, netloc, soc): + i = netloc.find(':') + if i >= 0: + host_port = netloc[:i], int(netloc[i+1:]) + else: + host_port = netloc, 80 + print "\t" "connect to %s:%d" % host_port + try: soc.connect(host_port) + except socket.error, arg: + try: msg = arg[1] + except: msg = arg + self.send_error(404, msg) + return 0 + return 1 + + def do_CONNECT(self): + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + if self._connect_to(self.path, soc): + self.log_request(200) + self.wfile.write(self.protocol_version + + " 200 Connection established\r\n") + self.wfile.write("Proxy-agent: %s\r\n" % self.version_string()) + self.wfile.write("\r\n") + self._read_write(soc, 300) + finally: + print "\t" "bye" + soc.close() + self.connection.close() + + def do_GET(self): + (scm, netloc, path, params, query, fragment) = urlparse.urlparse( + self.path, 'http') + if scm != 'http' or fragment or not netloc: + self.send_error(400, "bad url %s" % self.path) + return + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + if self._connect_to(netloc, soc): + self.log_request() + soc.send("%s %s %s\r\n" % ( + self.command, + urlparse.urlunparse(('', '', path, params, query, '')), + self.request_version)) + self.headers['Connection'] = 'close' + del self.headers['Proxy-Connection'] + for key_val in self.headers.items(): + soc.send("%s: %s\r\n" % key_val) + soc.send("\r\n") + self._read_write(soc) + finally: + print "\t" "bye" + soc.close() + self.connection.close() + + def _read_write(self, soc, max_idling=20): + iw = [self.connection, soc] + ow = [] + count = 0 + while 1: + count += 1 + (ins, _, exs) = select.select(iw, ow, iw, 3) + if exs: break + if ins: + for i in ins: + if i is soc: + out = self.connection + else: + out = soc + data = i.recv(8192) + if data: + out.send(data) + count = 0 + else: + print "\t" "idle", count + if count == max_idling: break + + do_HEAD = do_GET + do_POST = do_GET + do_PUT = do_GET + do_DELETE=do_GET + +class ThreadingHTTPServer (SocketServer.ThreadingMixIn, + BaseHTTPServer.HTTPServer): pass + +if __name__ == '__main__': + from sys import argv + if argv[1:] and argv[1] in ('-h', '--help'): + print argv[0], "[port [allowed_client_name ...]]" + else: + if argv[2:]: + allowed = [] + for name in argv[2:]: + client = socket.gethostbyname(name) + allowed.append(client) + print "Accept: %s (%s)" % (client, name) + ProxyHandler.allowed_clients = allowed + del argv[2:] + else: + print "Any clients will be served..." + BaseHTTPServer.test(ProxyHandler, ThreadingHTTPServer) |