"""HTTP Server This module contains a HTTP server """ import threading import socket from composer import ResponseComposer from parser import RequestParser import weblogging as logging from config import config class ConnectionHandler(threading.Thread): """Connection Handler for HTTP Server""" def __init__(self, conn_socket, addr, timeout): """Initialize the HTTP Connection Handler Args: conn_socket (socket): socket used for connection with client addr (str): ip address of client timeout (int): seconds until timeout """ super(ConnectionHandler, self).__init__() self.daemon = True self.conn_socket = conn_socket self.addr = addr self.timeout = timeout def handle_connection(self): """Handle a new connection""" self.rp = RequestParser() self.rc = ResponseComposer(timeout=self.timeout) while True: data = self.conn_socket.recv(4096) if len(data) == 0: break self.handle_data(data) self.conn_socket.close() def handle_data(self, data): for req in self.rp.parse_requests(data): logging.info("<-- (%s) %s" % (self.addr[0], req.startline())) resp = self.rc.compose_response(req) logging.info("--> (%s) %s" % (self.addr[0], resp.startline())) self.send(resp) def send(self, data): sent = self.conn_socket.send(str(data)) if sent == 0: raise RuntimeError('Socket broken') def run(self): """Run the thread of the connection handler""" try: self.handle_connection() except socket.error, e: print('ERR ' + str(e)) class Server: """HTTP Server""" def __init__(self, configfile, **kwargs): """Initialize the HTTP server Args: hostname (str): hostname of the server server_port (int): port that the server is listening on timeout (int): seconds until timeout """ self.read_config(configfile, **kwargs) self.done = False def read_config(self, configfile, **kwargs): config().read(configfile) if not config().has_section('webhttp'): config().add_section('webhttp') for name, val in kwargs.items(): if val != None: config().set('webhttp', name, str(val)) def run(self): """Run the HTTP Server and start listening""" self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind((config('hostname'), config('port', type=int))) self.socket.listen(config('max_connections', type=int)) while not self.done: (csocket, addr) = self.socket.accept() ch = ConnectionHandler(csocket, addr, config('timeout', type=int)) ch.start() def shutdown(self): """Safely shut down the HTTP server""" self.socket.shutdown(socket.SHUT_RDWR) self.socket.close() self.done = True