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()
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top