2 "exec" "python" "-O" "$0" "$@"
4 __doc__
= """Tiny HTTP Proxy.
6 This module implements GET, HEAD, POST, PUT and DELETE methods
7 on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
8 method is also implemented experimentally, but has not been
11 Any help will be greatly appreciated. SUZUKI Hisao
16 import BaseHTTPServer
, select, socket
, SocketServer
, urlparse
18 class ProxyHandler
(BaseHTTPServer.BaseHTTPRequestHandler
):
19 __base
= BaseHTTPServer.BaseHTTPRequestHandler
20 __base_handle
= __base.handle
22 server_version
= "TinyHTTPProxy/" + __version__
23 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 host_port
= netloc
[:i
], int
(netloc
[i
+1:])
38 host_port
= netloc
, 80
39 print
"\t" "connect to %s:%d" % host_port
40 try
: soc.connect
(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
]
94 (ins
, _
, exs
) = select.
select(iw
, ow
, iw
, 3)
107 print
"\t" "idle", count
108 if count
== max_idling
: break
115 class ThreadingHTTPServer
(SocketServer.ThreadingMixIn
,
116 BaseHTTPServer.HTTPServer
): pass
118 if __name__
== '__main__':
120 if argv
[1:] and argv
[1] in ('-h', '--help'):
121 print argv
[0], "[port [allowed_client_name ...]]"
125 for name
in argv
[2:]:
126 client
= socket.gethostbyname
(name
)
127 allowed.append
(client
)
128 print
"Accept: %s (%s)" % (client
, name
)
129 ProxyHandler.allowed_clients
= allowed
132 print
"Any clients will be served..."
133 BaseHTTPServer.
test(ProxyHandler
, ThreadingHTTPServer
)