habitat.http: message insertion by HTTP POST

habitat.http: a HTTP Gateway.

This module lets clients insert messages into the a habitat.message_server.Server by HTTP POST

class habitat.http.InsertApplication(server, program)[source]

InsertApplication contains high level “actions” of the HTTP gateway

The methods in this class are the ones that carry out the action requested by the HTTP client, and are independent of the CGI or HTTP server or protocol used.

server: a habitat.message_server.Server object into which the message action will insert items.

program: a habitat.main.Program object, of which the habitat.main.Program.shutdown() is used.

actions

a list of methods that a client is allowed to invoke

message(ip, args)[source]

Push Action

ip: string - the IP address of the client

Arguments should be supplied in args; the following arguments are required: “callsign”, “type”, “time_created”, “time_uploaded”, “data”. All are user supplied strings.

class habitat.http.SCGIApplication(server, program, socket_file, timeout=1)[source]

SCGIApplication is a simple, threaded SCGI server.

This class uses SocketServer to create a threaded SCGI server inside the main message server process, that can be shut down gracefully. It listens on a UNIX socket.

The following arguments to __init__ are passed to the initialiser of InsertApplication:

The following arguments to __init__ are passed to the initialiser of SocketServer.UnixStreamServer

  • socket_file: string - the path of the socket to listen on

timeout: the timeout for all connections handled by the SCGI server.

start()[source]

start the SCGI server

shutdown()[source]

gracefully shutdown the SCGI server and join every thread

class habitat.http.SCGIHandler(request, client_address, server)[source]

SCGIHandler objects are responsible for handling a single request

This class parses and handles the SCGI request, then returns a response to the client. An action (self.server.action_method, e.g., InsertApplication.message()) is called to perform the action requested by the client, where self.server typically is a SCGIApplication object, which is a subclass of InsertApplication, where those action methods are defined.

setup()[source]

prepares the SCGIHandler object for use

handle()[source]

reads the request and performs the action

read_scgi_req()[source]

parses the whole SCGI request

check_scgi_environ()[source]

sanity-check the environment provided

perform_req()[source]

perform the action requested by the user and return a response

SocketServer.py hack

The following code is quoted from Python’s SocketServer.py (Python Software Foundation License Version 2):

# Python 2.6.5: SocketServer.py

def __init__(self, server_address, RequestHandlerClass):
    (...)
    self.__is_shut_down = threading.Event()
    self.__serving = False

def serve_forever(self, poll_interval=0.5):
    self.__serving = True
    self.__is_shut_down.clear()
    while self.__serving:
        (...)
    self.__is_shut_down.set()

def shutdown(self):
    self.__serving = False
    self.__is_shut_down.wait()

# Python 2.7.0: SocketServer.py

def __init__(self, server_address, RequestHandlerClass):
    (...)
    self.__is_shut_down = threading.Event()
    self.__shutdown_request = False

def serve_forever(self, poll_interval=0.5):
    self.__is_shut_down.clear()
    try:
        while not self.__shutdown_request:
            (...)
    finally:
        self.__shutdown_request = False
        self.__is_shut_down.set()

def shutdown(self):
    self.__shutdown_request = True
    self.__is_shut_down.wait()

# Program:

def start(self):
    self.accept_thread = threading.Thread(target=self.serve_forever)
    (...)
    self.accept_thread.start()

# The issue in 2.6.5
#
# Main thread: test            Accept thread
# accept_thread.start()
# server.shutdown()
# self.__serving = False
# self.__is_shut_down.wait()
#                              server.serve_forever()
#                              self.__serving = True
# Hence it never shuts down and deadlocks.

The Python 2.7 implementation is more robust, and supports starting serve_forever in a thread followed by the quick calling of shutdown. This is admittedly not typcal use, but the habitat tests will cause this problem.

Hence the following hack in habitat.http.SCGIApplication.start is required. If the SocketServer has a __serving attribute (i.e., Python 2.6.5) then we wait for it to become true before returning from start:

try:
    while not self._BaseServer__serving:
        time.sleep(0.001)
except AttributeError:
    pass

Table Of Contents

Previous topic

habitat.archive: Storing messages in CouchDB

Next topic

habitat.main: the main method

This Page