All pastes #838584 Raw Edit

timmeh

public python v1 · immutable
#838584 ·published 2007-12-30 14:28 UTC
rendered paste body
__author__='Timothy Wakeham (timmeh)'__date__='31/12/07'__runas__='__main__'__desc__='Threaded HTTP server'import SocketServerimport loggingimport sysimport threadingimport stringimport relogging.basicConfig(level=logging.DEBUG, format='%(asctime)s - [%(levelname)s] %(name)s.%(funcName)s: %(message)s',filename='server.log')class HTTPRequestHandler(SocketServer.BaseRequestHandler):    def __init__(self, request, addr, server):        '''Initialise HTTPRequestHandler'''        #setup file logger        self.logger = logging.getLogger('HTTPRequestHandler')        #also log to console        console = logging.StreamHandler()        self.logger.addHandler(console)        self.logger.debug('Initialising HTTPRequestHandler')        self.logger.debug('Connection to %s:%s accepted' % (addr[0], addr[1]))	self.implemented_methods = ['GET', 'HEAD', 'PUT']        self.error_no_mapping = {400:['Bad Request', 'Malformed request string. Do not repeat request without modification'],                                 501:['Not Implemented', 'Functionality not currently implemented']}                self.re_request = re.compile(r'(?P<method>.*?) (?P<resource>.*?) HTTP\/(?P<version>1\.[0-1])')	        SocketServer.BaseRequestHandler.__init__(self, request, addr, server)    def display_error(error_no,  desc=''):        self.send_header(sock)        err_desc, info = self.error_no_mapping[error_no]                output =  "<html><head><title>%s Error</title></head>" % error_no        output += "<body><h1>%s</h1><h2>%s</h2><p>%s</p><p>%s</p>" % (error_no, err_desc, info, desc)        output += "</body></html>"        self.request.send(output)        return 0    def send_header(self, content='text/html'):        self.request.send('Server: pHTTP/0.1\r\n')        self.request.send('Content-Type:%s\r\n' % content)        self.request.send('\r\n')    def setup(self):        '''Any setup for the request handler goes here'''        self.logger.debug('Setting up HTTPRequestHandler')        SocketServer.BaseRequestHandler.setup(self)    def handle(self):        '''Handle the HTTP request'''        self.logger.debug('Handling request')	        header = []        buffer = ''        while(1):            buffer += self.request.recv(1024)            header.extend(buffer.split('\r\n'))            buffer = header.pop()            if not buffer: break              self.logger.debug('Received header')                request = self.re_request.search(header[0])        if request:            method = request.group('method')            resource = request.group('resource')            http_ver = request.group('version')            if method not in self.implemented_methods:                self.request.send('HTTP/%s 501 Not Implemented' % version)                self.logger.debug('[501] Not Implemented - Method: %s' % method)                return self.display_error(501, desc='%s method not implemented on this server' % method)            self.request.send('HTTP/%s 200 OK\r\n' % http_ver)	    self.send_header(content='text/plain')            self.logger.debug('Requested resource - %s' % resource)            self.request.send(string.join(header, '\r\n'))        else:            self.request.send('HTTP/%s 400 Bad Request' % version)            self.logger.debug('[400] Bad Request - Request: %s' % header[0])            return self.display_error(400,  desc='Request: %s' % header[0])                    self.logger.debug('Request sent')          def finish(self):        '''Finalise any cleanup needed'''        self.logger.debug('Finalise request')class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):    def __init__(self, addr, handler_class=HTTPRequestHandler):        '''Initialise TCP Socket Server'''        self.logger = logging.getLogger('HTTPServer')        #also log to console        console = logging.StreamHandler()        self.logger.addHandler(console)        self.logger.debug('Initialising threaded HTTP Server')        SocketServer.TCPServer.__init__(self, addr, handler_class)    def server_activate(self):        '''Called by constructor to start server'''        self.logger.debug('Server activated')        SocketServer.TCPServer.server_activate(self)    def serve_forever(self):        '''Start server'''        self.logger.debug('Listening...')        self.logger.info('Handling requests, <Ctrl-C> to quit')        while(1):            self.handle_request()        return    def handle_request(self):        '''Handle one request, possibly blocking'''        self.logger.debug('Request received')        return SocketServer.TCPServer.handle_request(self)    def verify_request(self, req, addr):        '''Verify the request - return True to continue handline'''        #put stuff here to deal with blocked IP adresses        if not addr: addr='Unknown'        self.logger.debug('Verifying request from: %s:%s...' % (addr[0], addr[1]))        verified = SocketServer.TCPServer.verify_request(self, req, addr)        if not verified:            self.logger.debug('Verification failed! [End process]')            return 0        self.logger.debug('Verification succeeded!')        return 1    def process_request(self, req, addr):        '''Actually process the request'''        self.logger.debug('Processing request...')        try:            processed = SocketServer.ThreadingMixIn.process_request(self, req, addr)        except:            exc, exc_str = sys.exc_info()            self.logger.critical('%s whilst processing request from %s:%s' % (exc_str, addr[0], addr[1]))            return 0        else:            return processed    def finish_request(self, req, addr):        '''Finalise anything to do with this request'''        self.logger.debug('Finalised processing')        return SocketServer.TCPServer.finish_request(self, req, addr)    def server_close(self):        '''Stop serving'''        self.logger.debug('Server closed, [End listening]')        return SocketServer.TCPServer.server_close(self)    def close_request(self, addr):        '''Finalise request'''            self.logger.debug('Request finalised [Close connection]')        return SocketServer.TCPServer.close_request(self, addr)if __name__ == '__main__':    logger = logging.getLogger('__main__')    #also log to console    console = logging.StreamHandler()    logger.addHandler(console)    addr = ('127.0.0.1', 0)    server = ThreadingTCPServer(addr, HTTPRequestHandler)    ip, port = server.server_address    logger.info('Server bound to address - %s:%s' % (ip, port))        server_thread = threading.Thread(target=server.serve_forever)    server_thread.setDaemon(1)    #server_thread.start()    server.serve_forever()