I want to provide one of my applications with a web interface. To achieve that, I subclass BaseHTTPRequestHandler
from the BaseHTTPServer
package (into a class I call _RequestHandler
) and implement my own handlers for HTTP HEAD / GET / POST / PUT
requests.
When I get a request for a "normal file", I just open it, read it from the file system and serve it to the browser. That works fine. However, being a web interface, I also want to communicate certain requests to the application backend. To do this, I want my server to provide an interface, over which callback functions for certain URLs can be registered (by the backend), which will be called when there is a request incoming for the registered URL and pass the request head and body to the request handler (= callback function) registered for that URL.
I. e. I want to be able to do something like this.
def callback_function(request):
# Do some processing.
return response
srv = WebServer(port = 8080, webroot = "htdocs/")
srv.register("/cgi-bin/test", callback_function)
srv.run()
Now, when someone requests some arbitrary URL with the browser, that has not been registered, the web server will load the specified file (relative to a the "web root") and deliver it.
I know how to implement this in principle. Place the URLs that should be handled differently in a dictionary. For each request, check if the requested URL is in the dictionary. If yes, put the request data (HTTP header and body) into a "request object", call the callback function registered for that URL and pass it that request object. Acquire the response object from the callback function, extract its contents (HTTP header and body) and serve it to the client. If the URL is not in the "special handled" dictionary, just load the file from the file system (relative to the "web root") and serve it.
The problem is, that in order to run the web server, I have to do something like this.
server = HTTPServer(("localhost", port), _RequestHandler)
server.serve_forever()
Now the problem is that I cannot pass an object, an instance of _RequestHandler
to the constructor of HTTPServer
. I have to pass the class itself. HTTPServer
will create the instance for me, which will be inaccessible to me, so I cannot call methods on it and thus not register a callback function to it (or pass a dictionary of callback functions to the constructor or whatever).
What can I do? There must be some way of getting a custom data object into the _RequestHandler
instance, right? I mean if there isn't, then all that server stuff appears to be seriously restricted. I don't see how I can do that though, since I don't have access to the instance of _RequestHandler
. It will be created by the HTTPServer
class for me and not be passed to the outside.
Any suggestions?