Search code examples
pythonsuperclassbasehttprequesthandler

Override BaseHTTPRequestHandlerClass


I'm setting up my first HTTP server that stores POST requests. I have a problem with the handler class BaseHTTPRequestHandler. In my approach I want to pass to the handler the response code I want the server will respond to the client (automatic tests purposes). I found a lot of help here and I'll share the code below for what concern the subclass I've developed, but I still need to figure it out how to init my handler since I don't know where to get the parameters: "request", "client_address" and "server". I've put three question marks in their respective position. Thank you for the help and sorry for the bad explanation.

class ServerHandler(BaseHTTPRequestHandler):

    def __init__(self, response_code, request, client_address, server):
        super().__init__(request, client_address, server)
        self.response_code = response_code

    def _set_header(self):
        self.send_response(self.response_code)
        self.send_header('content-type', 'text/html')
        self.end_headers()

    def do_HEAD(self):
        self._set_header()

    def do_POST(self):
        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD': 'POST'}
        )

        # get POST data
        utc = int(form.getvalue("utc"))
        value = form.getvalue("value")
        sn = form.getvalue("sn")

        # manage data
        dataManager(utc, sn, value)

        # send response
        self._set_header()
        response = "<RESULT>0</RESULT>"
        self.wfile.write(response.encode('utf-8'))


class Server:

    def __init__(self, port, response_code=200, server_class=HTTPServer):
        self.port = port
        self.response_code = response_code
        self.server_address = ('', self.port)
        handler_class = ServerHandler(self.response_code, ?, ?, ?)
        self.server = server_class(self.server_address, handler_class)
        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True

    def run(self):
        self.server_thread.start()
        print("Server started")

    def shutdown(self):
        self.server.shutdown()
        self.server.server_close()
        print("Server stopped")

Solution

  • I solved doing the following. Instead of passing response_code as a function parameter, I add response_code as a class variable and from the class Server I write directly on the public class variable response_code. That's it. Not the best solution but it works. Please let me know if you have better ideas.

    class ServerHandler(BaseHTTPRequestHandler):
    
    def __init__(self, request, client_address, server):
        super().__init__(request, client_address, server)
        self.response_code = response_code
    
    def _set_header(self):
        self.send_response(self.response_code)
        self.send_header('content-type', 'text/html')
        self.end_headers()
    
    def do_HEAD(self):
        self._set_header()
    
    def do_POST(self):
        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD': 'POST'}
        )
    
        # get POST data
        utc = int(form.getvalue("utc"))
        value = form.getvalue("value")
        sn = form.getvalue("sn")
    
        # manage data
        dataManager(utc, sn, value)
    
        # send response
        self._set_header()
        response = "<RESULT>0</RESULT>"
        self.wfile.write(response.encode('utf-8'))  
    
    class Server:
    
    def __init__(self, port, response_code=200, server_class=HTTPServer):
        self.port = port
        self.server_address = ('', self.port)
        handler_class = ServerHandler
        handler_class.response_code = response_code
        self.server = server_class(self.server_address, handler_class)
        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
    
    def run(self):
        self.server_thread.start()
        print("Server started")
    
    def shutdown(self):
        self.server.shutdown()
        self.server.server_close()
        print("Server stopped")