- 论坛徽章:
- 2
|
前几天写的HTTP代理服务器 lightproxy.py, 除掉空行在100行以内
- #!/usr/bin/env python
- from select import select
- from socket import socket
- from sys import argv, exit
- from urlparse import urlparse, urlunparse
- from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
- from SocketServer import ThreadingMixIn
- __version__ = '0.01'
- bufsize = 1024 * 1024 # 1MB
- timeout = 60
- class ProxyHandler(BaseHTTPRequestHandler):
- server_version = 'SimpleProxy/%s' % __version__
- def do_CONNECT(self):
- self.log_request()
- sock = socket()
- self._connect_remote(sock, self.path)
- self.wfile.write('%s 200 Connection Established\r\n'
- % self.protocol_version)
- self.wfile.write('Proxy-agent: %s\r\n' % self.version_string())
- self.wfile.write('\r\n')
- self._do_proxy(sock)
- self.connection.close()
- sock.close()
- def do_GET(self):
- import time
- print time.ctime()
- self.log_request()
- res = urlparse(self.path)
- if res.scheme != 'http' or res.fragment or not res.netloc:
- self.send_error(400, 'bad url %s' % self.path)
- raise RuntimeError('bad url %s' % self.path)
- sock = socket()
- self._connect_remote(sock, res.netloc)
- path = urlunparse(('', '', res.path, res.params, res.query, '')) or '/'
- sock.send('%s %s %s\r\n' % (self.command, path, self.request_version))
- self.headers['Connection'] = 'close'
- del self.headers['Proxy-Connection']
- for header in self.headers:
- sock.send('%s: %s\r\n' % (header, self.headers[header]))
- sock.send('\r\n')
- self._do_proxy(sock)
- self.connection.close()
- sock.close()
- def _connect_remote(self, sock, path):
- if ':' in path:
- host, port = path.split(':')
- port = int(port)
- remote = host, port
- else:
- remote = (path, 80)
- sock.connect(remote)
- def _do_proxy(self, sock, timeout=timeout):
- client, server = self.connection, sock
- cs = [client, server]
- while 1:
- rlist, wlist, xlist = select(cs, [], cs, timeout)
- if xlist:
- who = 'client' if client in xlist else 'server'
- raise RuntimeError('exceptional condition from %s' % who)
- if rlist:
- for reader in rlist:
- writer = client if reader is server else server
- data = reader.recv(bufsize)
- if not data:
- return
- writer.send(data)
- else:
- raise RuntimeError('timeout')
- class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
- pass
- def serve(addr, server=ThreadingHTTPServer):
- print 'Serving HTTP Proxy on %s' % str(addr)
- server(addr, ProxyHandler).serve_forever()
- def parse_argv(argv=argv):
- if len(argv) == 1:
- addr = ('0.0.0.0', 8000)
- else:
- arg = argv[1]
- if arg in ('-h', '--help', '-help', 'help'):
- show_help(argv[0])
- exit(1)
- if ':' in arg:
- host, port = arg.split(':')
- addr = (host, int(port))
- else:
- addr = ('0.0.0.0', int(arg))
- return addr
- def show_help(progname=None):
- progname = progname or argv[0]
- print 'Usage: %s [[host:]port]'
- if __name__ == '__main__':
- addr = parse_argv()
- serve(addr)
复制代码 其实我是为了把ssh dynamic forwarding的socks5代理转换成更为通用的http代理,这样可以直接指定http_proxy环境变量来控制程序使用代理的行为
于是又写了个socks2http.py
- #!/usr/bin/env python
- from sys import argv
- import lightproxy
- import socks
- def init_proxy(socks_host, socks_port):
- socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS4, socks_host, socks_port)
- lightproxy.socket = socks.socksocket
- def parse_argv(argv=argv):
- if len(argv) == 1 or argv[1] in ('-h', '--help', '-help', 'help'):
- show_help(argv[0])
- exit(1)
- arg = argv[1]
- socks_host, socks_port = arg.split(':')
- socks_port = int(socks_port)
- addr = lightproxy.parse_argv([argv[0]] + argv[2:])
- return (socks_host, socks_port), addr
- def show_help(progname=None):
- progname = progname or argv[0]
- print 'Usage: %s socks_host:socks_port [[host:]port]' % progname
- def main():
- socks_proxy, addr = parse_argv()
- init_proxy(*socks_proxy)
- lightproxy.serve(addr)
- if __name__ == '__main__':
- main()
复制代码 后来我把lightproxy.py增加了gevent支持,代码约增加了40行 |
|