I have a special database class instance that i want passed into an HTTPServer handler so that I can have it returned for use in my do_GET and do_POST callback handlers. I tried subclassing to add my database class as an additional argument to the Handler... However that does not get it all the way down into my HTTPServerRequestHandler class.
What I also tried that did not work:
Even if I do manage to get the argument added to the HTTPServerRequestHandler class, this only creates an error because the serve_forever will still callback the class using the original 4 (self+3) arguments, omitting my 5th (database) argument.
Previously, I would instantiate the database class as a Global constant, but that seems like a bad idea.
Here is what I have working so far:
This code successfully serves my page, but I have no access to any of the database methods (including my log handler, which is a part of the database instance):
def run_server(state_database, port):
state_database.log.info('starting server.')
server_address = ('', port)
HandlerClass = MakeHandlerClassforDB(state_database)
httpserver = HTTPServer(server_address, HandlerClass)
state_database.log.info('Server loaded.')
httpserver.serve_forever()
def MakeHandlerClassforDB(state_database):
class CustomHandler(HTTPServerRequestHandler, object):
def __init__(self, *args, **kwargs):
self.database = state_database
super(CustomHandler, self).__init__(*args, **kwargs)
return CustomHandler
# HTTPRequestHandler class
# noinspection PyPep8Naming
class HTTPServerRequestHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
# would like to be able to get database into here as a self....
def do_GET(self):
ip = self.client_address[0].split(".")
if ip[0] in self.page.blocked_ip_highs:
# `self.database` does not resolve, so this does not work...
self.database.log.info(
"Ignored request from %s" % self.client_address)
return
...
def do_POST(self):
time_start = time.time()
# again, self.database does not exist in the callback
self.database.log.debug(
"Headers_________\n%s\n______________\n" % self.headers)
I also want this to work on both Python 3 and Python 2 (which is why I don't use super().__init__(...)
.)
This appears to work:
def run_server(state_database, port):
server_address = ('', port)
handlerclass = makehandlerclassfordb(state_database)
httpserver = HTTPServer(server_address, handlerclass)
httpserver.serve_forever()
def makehandlerclassfordb(state_database):
class CustomHandler(HTTPServerRequestHandler, object):
def __init__(self, *args, **kwargs):
self.database = state_database
self.page = HTMLPage()
super(CustomHandler, self).__init__(*args, **kwargs)
return CustomHandler
class HTTPServerRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.database.log.debug(
"Get Header_________%s______________" % self.headers)
"""both self.page and self.database DO resolve (although
PyCharm does not think they should :P )"""
ip = self.client_address[0].split(".")
if ip[0] in self.page.blocked_ip_highs:
self.database.log.info(
"Ignored request from %s" % self.client_address)
return
I could re-add the items to the class HTTPServerRequestHandler __init__
, but this does not change the functionality and I see no reason to just to make an IDE error go away.