Peano
Loading...
Searching...
No Matches
TinyHTTPProxy.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3"""Tiny HTTP Proxy
4
5This module implements GET, HEAD, POST, PUT, DELETE and CONNECT methods
6on BaseHTTPServer (or server.http), and behaves as an HTTP proxy.
7"""
8
9from __future__ import print_function
10
11__version__ = "1.1.1"
12
13import select, socket, sys
14
15try:
16 import http.server as hserv
17 from socketserver import ThreadingMixIn
18 import urllib.parse as urlparse
19 print_word = lambda wd: print(wd, end="\t", flush=True)
20 _ = lambda s: s.encode('utf-8')
21except ImportError:
22 import BaseHTTPServer as hserv
23 from SocketServer import ThreadingMixIn
24 import urlparse
25 print_word = lambda s: (print(s, end="\t"), sys.stdout.flush())
26 _ = lambda s: s
27
28class ProxyHandler (hserv.BaseHTTPRequestHandler):
29 __base = hserv.BaseHTTPRequestHandler
30 __base_handle = __base.handle
31
32 server_version = "TinyHTTPProxy/" + __version__
33 rbufsize = 0 # self.rfile Be unbuffered
34
35 def handle(self):
36 (ip, port) = self.client_address
37 if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients:
38 self.raw_requestline = self.rfile.readline()
39 if self.parse_request(): self.send_error(403)
40 else:
41 self.__base_handle()
42
43 def _connect_to(self, netloc, soc):
44 i = netloc.find(':')
45 if i >= 0:
46 host_port = netloc[:i], int(netloc[i+1:])
47 else:
48 host_port = netloc, 80
49 print("\t" "connect to %s:%d" % host_port)
50 try: soc.connect(host_port)
51 except socket.error as arg:
52 try:
53 msg = arg[1]
54 except:
55 msg = arg
56 self.send_error(404, msg)
57 return False
58 return True
59
60 def do_CONNECT(self):
61 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
62 try:
63 if self._connect_to(self.path, soc):
64 self.log_request(200)
65 self.wfile.write(_(self.protocol_version +
66 " 200 Connection established\r\n"))
67 self.wfile.write(_("Proxy-agent: %s\r\n" %
68 self.version_string()))
69 self.wfile.write(b"\r\n")
70 self._read_write(soc, 300)
71 finally:
72 print_word("bye")
73 soc.close()
74 self.connection.close()
75
76 def do_GET(self):
77 (scm, netloc, path, params, query, fragment) = urlparse.urlparse(
78 self.path, 'http')
79 if scm != 'http' or fragment or not netloc:
80 self.send_error(400, "bad url %s" % self.path)
81 return
82 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
83 try:
84 if self._connect_to(netloc, soc):
85 self.log_request()
86 soc.send(_("%s %s %s\r\n" % (
87 self.command,
88 urlparse.urlunparse(('', '', path, params, query,
89 '')),
91 self.headers['Connection'] = 'close'
92 del self.headers['Proxy-Connection']
93 for key_val in self.headers.items():
94 soc.send(_("%s: %s\r\n" % key_val))
95 soc.send(b"\r\n")
96 self._read_write(soc)
97 finally:
98 print_word("bye")
99 soc.close()
100 self.connection.close()
101
102 def _read_write(self, soc, max_idling=20):
103 iw = [self.connection, soc]
104 ow = []
105 count = 0
106 while True:
107 count += 1
108 (ins, _, exs) = select.select(iw, ow, iw, 3)
109 if exs:
110 break
111 if ins:
112 for i in ins:
113 if i is soc:
114 out = self.connection
115 else:
116 out = soc
117 data = i.recv(8192)
118 if data:
119 out.send(data)
120 count = 0
121 else:
122 print_word(count)
123 if count == max_idling:
124 break
125
126 do_HEAD = do_GET
127 do_POST = do_GET
128 do_PUT = do_GET
129 do_DELETE = do_GET
130 do_OPTIONS = do_GET
131
132class ThreadingHTTPServer (ThreadingMixIn, hserv.HTTPServer):
133 pass
134
135def main(argv):
136 if argv[1:] and argv[1] in ('-h', '--help'):
137 print(argv[0], "[port [allowed_client_name ...]]")
138 else:
139 server_address = ('', int(argv[1]) if argv[1:] else 8000)
140 if argv[2:]:
141 allowed = []
142 for name in argv[2:]:
143 client = socket.gethostbyname(name)
144 allowed.append(client)
145 print("Accept: %s (%s)" % (client, name))
146 ProxyHandler.allowed_clients = allowed
147 else:
148 print("Any clients will be served...")
149 httpd = ThreadingHTTPServer(server_address, ProxyHandler)
150 (host, port) = httpd.socket.getsockname()
151 print("Serving", ProxyHandler.protocol_version,
152 "on", host, "port", port, "...")
153 httpd.serve_forever()
154
155if __name__ == '__main__':
156 main(sys.argv)
_read_write(self, soc, max_idling=20)
_connect_to(self, netloc, soc)