3 __doc__ = """Tiny HTTP Proxy.
5 This module implements GET, HEAD, POST, PUT and DELETE methods
6 on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
7 method is also implemented experimentally, but has not been
10 Any help will be greatly appreciated. SUZUKI Hisao
15 import BaseHTTPServer, select, socket, SocketServer, urlparse, re
17 class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler):
18 __base = BaseHTTPServer.BaseHTTPRequestHandler
19 __base_handle = __base.handle
21 server_version = "TinyHTTPProxy/" + __version__
22 rbufsize = 0 # self.rfile Be unbuffered
26 (ip, port) = self.client_address
27 if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients:
28 self.raw_requestline = self.rfile.readline()
29 if self.parse_request(): self.send_error(403)
33 def _connect_to(self, netloc, soc):
36 self.host_port = netloc[:i], int(netloc[i+1:])
38 self.host_port = netloc, 80
39 print "\t" "connect to %s:%d" % self.host_port
40 try: soc.connect(self.host_port)
41 except socket.error, arg:
44 self.send_error(404, msg)
49 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
51 if self._connect_to(self.path, soc):
53 self.wfile.write(self.protocol_version +
54 " 200 Connection established\r\n")
55 self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
56 self.wfile.write("\r\n")
57 self._read_write(soc, 300)
61 self.connection.close()
64 (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
66 if scm != 'http' or fragment or not netloc:
67 self.send_error(400, "bad url %s" % self.path)
69 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
71 if self._connect_to(netloc, soc):
73 soc.send("%s %s %s\r\n" % (
75 urlparse.urlunparse(('', '', path, params, query, '')),
76 self.request_version))
77 self.headers['Connection'] = 'close'
78 del self.headers['Proxy-Connection']
79 for key_val in self.headers.items():
80 soc.send("%s: %s\r\n" % key_val)
86 self.connection.close()
88 def _read_write(self, soc, max_idling=20):
89 iw = [self.connection, soc]
95 (ins, _, exs) = select.select(iw, ow, iw, 3)
101 out = self.connection
106 if (re.match("(\w+\.)*gnunet", self.host_port[0])):
107 arr = self.host_port[0].split(' ')
109 data = re.sub(r'(a href="http://(\w+\.)*)(\+)', r'\1'+self.host_port[0], data)
114 print "\t" "idle", count
116 if count == max_idling: break
123 class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
124 BaseHTTPServer.HTTPServer): pass
126 if __name__ == '__main__':
128 if argv[1:] and argv[1] in ('-h', '--help'):
129 print argv[0], "[port [allowed_client_name ...]]"
133 for name in argv[2:]:
134 client = socket.gethostbyname(name)
135 allowed.append(client)
136 print "Accept: %s (%s)" % (client, name)
137 ProxyHandler.allowed_clients = allowed
140 print "Any clients will be served..."
141 BaseHTTPServer.test(ProxyHandler, ThreadingHTTPServer)