1 #!/usr/bin/env python
  2 # encoding: utf-8
  3 import logging, urlparse
  4 
  5 class Server(object):
  6     def __init__(self):
  7         self.dfuncs = dict()
  8         self.modules = dict()
  9     def serve(self, req):
 10         result = -1
 11         req_path = urlparse.urlsplit(req)[2]
 12         if req_path in self.dfuncs: dfunc = self.dfuncs[req_path] # in cache
 13         else: dfunc = self.load(req_path)  # handler function not in cache
 14         if dfunc: result = dfunc(req)
 15         return(result)
 16     def load(self, req_path):
 17         logging.debug("load() called for '%s'" % req_path)
 18         m = dfunc = None
 19         mpath = 'modules.%s' % '.'.join(filter(None, req_path.split('/')[:-1]))
 20         # already have the module needed?
 21         if mpath in self.modules: m = self.modules[mpath] # yes!
 22         else:   # no, try import
 23             try: m = __import__(mpath, globals(), locals(), ['ReqH'])
 24             except ImportError, e: logging.error(str(e))
 25             else: self.modules[m.__name__] = m  # cache it
 26         if m:
 27             # got the module, does it have a 'ReqH' class?
 28             if hasattr(m, 'ReqH'):
 29                 # yes, does the 'ReqH' class have a dispatch function?
 30                 if hasattr(m.ReqH, 'dispatch') and callable(m.ReqH.dispatch):
 31                     self.dfuncs[req_path] = dfunc = m.ReqH.dispatch
 32                 else: logging.error("no dispatch function in '%s'" % mpath)
 33             else: logging.error("no request handler class in '%s'" % mpath)
 34         return dfunc
 35 if __name__ == '__main__':
 36     logf = logging.Formatter('** %(asctime)s %(levelname)s - %(message)s')
 37     lcon = logging.StreamHandler()
 38     lcon.setFormatter(logf)
 39     logging.getLogger('').addHandler(lcon)
 40     logging.getLogger('').setLevel(logging.INFO)
 41     logging.info('starting server..')
 42     server = Server()
 43     while 1:
 44         req = raw_input("!! please type in a req in HTTP-GET format " \
 45                         "(or 'q' to quit)\n>>> ")
 46         if req == 'q': break
 47         result = server.serve(req)
 48         if result == 0: logging.info('S: %s' % req)
 49         else: logging.info('F: %s' % req)
 50     logging.info('server terminated')