Reference: http://docs.python.org/2/library/basehttpserver.html
I have the following code snippet which uses Python BaseHTTPServer
to run a basic HTTP server.
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
# http request handler
class HttpHandler(BaseHTTPRequestHandler):
def do_POST(self):
print "I have just received a HTTP request through POST"
try:
server = HTTPServer((<ip>, <port>), HttpHandler)
# wait forever for incoming http requests!
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()
What I am looking for is a way to get a callback whenever the http server is started/stopped using server.serve_forever()
/server.socket.close()
methods.
Say we have the following functions:
def http_server_start_callback():
print "http server has just been started"
def http_server_stop_callback():
print "http server has just been stopped"
I want http_server_start_callback
function to be called right after (whenever) I start the server i.e. server.serve_forever()
and I want http_server_stop_callback
function to be called right after (whenever) I stop the server i.e. server.socket.close()
It would be excellent to configure the http server with the following callbacks:
- before starting the server
- after starting the server
- before stopping the server
- after stopping the server
Is there a way to setup these callbacks in Python BaseHTTPServer.HTTPServer
?!
It would be excellent to configure the http server with the following
callbacks:
- before starting the server
- after starting the server
- before stopping the server
- after stopping the server
Bear in mind that the OS will start accepting and queuing TCP connections the moment the socket starts listening, which is done in the constructor of BaseHTTPServer
, so if you want to perform lengthy tasks before starting the server, it's probably better to do them before the OS starts accepting connections.
There's a server_activate()
method which makes the call to socket.listen()
, so it's probably best to override that.
Similarly, the OS will continue to accept connections until the call to socket.close()
, so if you want to be able to define a 'pre-stop' handler which has the capacity to prevent itself from being shutdown, it's probably better to use the server_close()
method, rather than calling socket.close()
directly.
I've put together a simple example, using class methods on the request handler to handle the four new events, although you can move them somewhere else...
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
# Subclass HTTPServer with some additional callbacks
class CallbackHTTPServer(HTTPServer):
def server_activate(self):
self.RequestHandlerClass.pre_start()
HTTPServer.server_activate(self)
self.RequestHandlerClass.post_start()
def server_close(self):
self.RequestHandlerClass.pre_stop()
HTTPServer.server_close(self)
self.RequestHandlerClass.post_stop()
# HTTP request handler
class HttpHandler(BaseHTTPRequestHandler):
@classmethod
def pre_start(cls):
print 'Before calling socket.listen()'
@classmethod
def post_start(cls):
print 'After calling socket.listen()'
@classmethod
def pre_stop(cls):
print 'Before calling socket.close()'
@classmethod
def post_stop(cls):
print 'After calling socket.close()'
def do_POST(self):
print "I have just received an HTTP POST request"
def main():
# Create server
try:
print "Creating server"
server = CallbackHTTPServer(('', 8000), HttpHandler)
except KeyboardInterrupt:
print "Server creation aborted"
return
# Start serving
try:
print "Calling serve_forever()"
server.serve_forever()
except KeyboardInterrupt:
print "Calling server.server_close()"
server.server_close()
if __name__ == '__main__':
main()
Note that I've also moved the call to the constructor into its own try...except
block, since the server
variable won't exist if you hit CTRL-C during its construction.
You have to subclass HTTPServer
and use your class instead HTTPServer
from __future__ import print_function
from BaseHTTPServer import HTTPServer
from BaseHTTPServer import BaseHTTPRequestHandler
class MyHTTPServer(HTTPServer):
def __init__(self, *args, **kwargs):
self.on_before_serve = kwargs.pop('on_before_serve', None)
HTTPServer.__init__(self, *args, **kwargs)
def serve_forever(self, poll_interval=0.5):
if self.on_before_serve:
self.on_before_serve(self)
HTTPServer.serve_forever(self, poll_interval)
# http request handler
class HttpHandler(BaseHTTPRequestHandler):
def do_POST(self):
print("I have just received a HTTP request through POST")
try:
server = MyHTTPServer(('0.0.0.0', 8080), HttpHandler,
on_before_serve = lambda server: print('Server will start to serve in the moment...'))
# wait forever for incoming http requests!
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()