public
Created

tornado http proxy

  • Download Gist
gistfile1.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#!/usr/bin/env python
#coding:utf-8
 
import sys, os, re
import logging
import socket
import urlparse
from tornado import iostream, ioloop
from tornado.httpserver import HTTPServer
from tornado import httputil
 
logging.basicConfig(level=logging.INFO, format='%(levelname)s - - %(asctime)s %(message)s', datefmt='[%d/%b/%Y %H:%M:%S]')
 
class LocalProxyHandler(object):
 
def __init__(self, request):
self.request = request
scheme, netloc, path, params, query, fragment = urlparse.urlparse(self.request.uri, 'http')
self.remote_host, self.remote_port = self.resolve_netloc(netloc)
self.remote_path = urlparse.urlunparse((scheme, self.remote_host + ('' if self.remote_host == 80 else ':%d' % self.remote_port), path, params, query, ''))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
self.remote_stream = iostream.IOStream(sock)
self.remote_stream.connect((self.remote_host, self.remote_port), self._on_remote_connect)
 
def resolve_netloc(self, netloc):
try:
host, _, port = netloc.rpartition(':')
return host, int(port)
except ValueError:
return netloc, 80
 
def _on_remote_connect(self):
logging.info('remote address (%r, %r) connected.', self.remote_host, self.remote_port)
data ='%s %s %s\r\n' % (self.request.method, self.remote_path, self.request.version)
self.request.headers['Connection'] = 'close'
self.request.headers['Proxy-Connection'] = 'close'
data += ''.join('%s: %s\r\n' % (k, v) for k,v in self.request.headers.get_all())
data += '\r\n'
self.remote_stream.write(data, self._on_remote_write)
 
def _on_remote_write(self):
logging.info('remote address (%r, %r) send data end.', self.remote_host, self.remote_port)
self.remote_stream.read_until('\r\n\r\n', self._on_remote_read_headers)
 
def _on_remote_read_headers(self, data):
logging.info('remote address (%r, %r) read headers end.', self.remote_host, self.remote_port)
eol = data.find('\r\n')
self.remote_headers = httputil.HTTPHeaders.parse(data[eol:])
self.request.connection.write(data, self._on_local_write_headers)
 
def _on_local_write_headers(self):
logging.info('remote address (%r, %r) to local write headers end.', self.remote_host, self.remote_port)
if self.remote_headers.get('connection') == 'close':
self.remote_stream.read_until_close(self._on_remote_read_body)
elif 'content-length' in self.remote_headers:
self.remote_stream.read_bytes(int(self.remote_headers['content-length']), self._on_remote_read_body)
else:
self.remote_stream.read_until_close(self._on_remote_read_body)
 
def _on_remote_read_body(self, data):
logging.info('remote address (%r, %r) read finish.', self.remote_host, self.remote_port)
self.request.write(data)
self.request.finish()
 
 
def main():
http_server = HTTPServer(LocalProxyHandler, no_keep_alive=True)
http_server.listen(8888)
ioloop.IOLoop.instance().start()
 
if __name__ == '__main__':
main()

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.