pythonpython-3.xhttpserverbasehttprequesthandler

Python: Instance of BaseHTTPRequestHandler resets after GET Request


I have a python BaseHTTPRequestHandler class that is called by an HTTPServer class. Basically the BaseHTTPRequestHandler just runs a basic algorithm and then responds to a Get request. The issue is that every time I do a Get request, I get the correct response but all the gathered data in BaseHTTPRequestHandler is reset as if each time a request is sent to the HTTPServer it creates a new instance of BaseHTTPRequestHandler. I can't find anything online that really explains what's going on behind the scenes. I've attached a simplified version of my code. Any help or explanation would be greatly appreciated.

Before anyone suggests creating a class or global variable, I am using a thread to create multiple instances of this class at once and doing so makes all the instances on each thread share and replace each other's data.

CODE (indentation off when copy and pasted)

BaseHTTPRequestHandler

This simplified version just keeps track of the number of alerts that have happened. The problem is that the count always resets to 0 when I call a Get request as if the instance of the class is reset.

class SimulationServer(BaseHTTPRequestHandler):
def __init__(self, address, port, randomNumberMax, *args):
    self.IP_ADDRESS = address
    self.PORT = port
    self.RANDOM_NUMBER_MAX = randomNumberMax
    self.COUNT = 0
    BaseHTTPRequestHandler.__init__(self, *args)

def do_GET(self):
    if self.headers['Authorization'] == 'Basic ' + str(key):
        print("send response")
        self.do_HEAD()
        randomNumberMax = self.RANDOM_NUMBER_MAX
        response = ""

        if randint(0, randomNumberMax) == 0:
            self.generateAlert()

        base_path = urlparse(self.path).path
        print('base_path: ' + base_path)
        if base_path == '/count':
            response = self.getCount()

        self.wfile.write(bytes(response, 'utf-8'))

def getCount(self):
    count = self.COUNT
    jsonString = '{"_sig": "","count": ' + str(count) + '}'
    return jsonString

def generateAlert(self):
    newAlert = {}
    newAlert['siteId'] = "siteId"+ str(self.COUNT)
    newAlert['mesg'] = "Simulated Alert"
    newAlert['when'] = int(time.time())

    self.COUNT += 1

HTTPServer

class CustomHTTPServer(HTTPServer):
key = ''

def __init__(self, address, handlerClass=SimulationServer):
    super().__init__(address, handlerClass)

def set_auth(self, username, password):
    self.key = base64.b64encode(
        bytes('%s:%s' % (username, password), 'utf-8')).decode('ascii')

def get_auth_key(self):
    return self.key

Main

This class creates the HTTPServer and attaches the handler

class RunSimulator(object):
def run(self, alertFrequency=50, port=9000):
    ipAddress="127.0.0.1"
    def handler(*args):
        SimulationServer(ipAddress, port, alertFrequency, *args)

    simulationServer = CustomHTTPServer((ipAddress, port), handler)
    simulationServer.set_auth('username', 'password')

    try:
        simulationServer.serve_forever()
    except KeyboardInterrupt:
        pass

    simulationServer.server_close()
    print(time.asctime(), "Server Stops - %s:%s" % (ipAddress, port))

if __name__ == "__main__":
    from sys import argv
    simu = RunSimulator()
    simu.run()

Solution

  • So the short answer is that it does create a new instance every time a request is sent.

    BaseHTTPServer.HTTPServer is a subclass of SocketServer.TCPServer which itself is a subclass of SocketServer.BaseServer. Every time a request comes in it will process the request process_request and then call finish_request. finish_request will instantiate a fresh instance of whatever your request handler is.