From aded31dced21f97fb3fc8ff54983020d85fbe134 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Sat, 6 Feb 2010 00:15:26 -0200 Subject: [PATCH] http: tiny-http-proxy Signed-off-by: Luiz Capitulino --- http/tiny-http-proxy | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100755 http/tiny-http-proxy diff --git a/http/tiny-http-proxy b/http/tiny-http-proxy new file mode 100755 index 0000000..7a92530 --- /dev/null +++ b/http/tiny-http-proxy @@ -0,0 +1,121 @@ +#!/usr/bin/python +# +# A Tiny HTTP Proxy. +# +# TODO: +# +# - Doesn't understand chunked data +# - Try: www.wikipedia.org +# +# Luiz Capitulino + +import socket +from sys import argv, exit, stderr + +class HttpMessage: + def get_server(self): + uri = self.header.split()[1] + return uri[uri.find('//') + 2:uri.rfind('/')] + + def conn_close(self): + for line in self.header.split('\n'): + if line.startswith('Connection') and line.find('close') != -1: + return True + return False + + def __repr__(self): + return self.message + + def __init__(self, header, body): + self.header = header + self.body = body + self.message = self.header + if self.body: + self.message += self.body + print self.header + +class TinyHttpProxy: + def __read_header(self, sock): + header = '' + in_end = False + while True: + b = sock.recv(1) + header += b + if not b: + return + if b == '\r': + continue + elif b != '\n': + in_end = False + continue + elif in_end: + return header + else: + in_end = True + + def __get_content_length(self, header): + for line in header.split('\n'): + if line.startswith('Content-Length'): + return int(line[line.find(' '):]) + return 0 + + def __read_body(self, header, sock): + buf = '' + len = self.__get_content_length(header) + for i in range(len): + buf += sock.recv(1) + return buf + + def __read_message(self, sock): + header = self.__read_header(sock) + if not header: + return + body = self.__read_body(header, sock) + return HttpMessage(header, body) + + def __create_proxy_sock(self, domain, port): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind((domain, port)) + s.listen(1) + return s + + def __server_connect(self, server, port): + ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ssock.connect((server, port)) + return ssock + + def main_loop(self): + while True: + ssock = None + (csock, addr) = self.sock.accept() + req = self.__read_message(csock) + while True: + if not ssock: + ssock = self.__server_connect(req.get_server(), 80) + ssock.sendall(req.message) + resp = self.__read_message(ssock) + if not resp: + ssock.close() + ssock = None + continue + csock.sendall(resp.message) + req = self.__read_message(csock) + if resp.conn_close(): + ssock.close() + csock.close() + break + + def __init__(self, domain, port): + self.sock = self.__create_proxy_sock(domain, port) + +def main(): + if len(argv) != 3: + print 'tiny-http-proxy ' + exit(1) + + server = TinyHttpProxy(argv[1], int(argv[2])) + server.main_loop() + +if __name__ == '__main__': + main() -- 2.11.4.GIT