======================= BaseHTTPObjectPublisher ======================= What is it? =========== BaseHTTPObjectPublisher is a simple object-publishing framework written on top of BaseHTTPServer.BaseHTTPRequestHandler. It provides a simple API to handle publishing of Python classes and callables to HTTP urls, and some helper functionality to build applications that use this. Public API ========== For a complete reference, check the code (XXX currently, will create py.apigen integration code later), here's a quick overview to get you started though: * BaseHTTPObjectPublisher.ObjectPublisherHandler A subclass of BaseHTTPServer.BaseHTTPRequestHandler that traverses an object tree to find resources based on a provided url (path), if a resource is found request handling is dispatched, if not, if something goes wrong, or if a special type of exception (HTTPError, see below) is raised, an error page is displayed. When a path is requested, it is split on '/' and traversed until a handler is found. All objects that are traversed should implement the Collection base class, except for the handler, which can be any type of callable. When traversing a Collection, its 'traverse' method is called with the remaining path as a tuple and the originally requested path as a string. This method should remove a bit of the path, and then either continue traversing the next collection, or return a handler (callable) for the url. Handlers are called with a reference to the path as first argument, the remaining path tuple as second (can be compared to PATH_INFO in CGI), and the query string for GET queries as third. They should either return a tuple (status, headers, body), where 'status' is an integer describing the status code, 'headers' is a dict used to generate the HTTP headers and 'body' is a string or file-like object (should provide at least a read() method that accepts an integer describing how many bytes to read, although it can be ignored if that suits the situation). To start an object publisher server, attach a variable called 'application' to the handler _class_ (so it's only instantiated once, not that this means it's shared all through the application) and start a BaseHTTPServer.HTTPServer instance, passing it the handler class on initlialization. A simple application that exposes two paths (/index and /hello, where /index would be called if just / was requested) would look something like this:: from BaseHTTPObjectPublisher import Collection, \ ObjectPublisherHandler, run_server def hellohandler(handler, path, query): """ handlers can be simple callables, or objects implementing a __call__ method handlers always have to have an 'exposed' attribute set to some True value (for this function this happens in MyApplication.__init__), else they're not exposed (a 404 is raised on access) """ return (200, {'Content-Type': 'text/plain'}, 'Hello, World') class MyApplication(Collection): """ an application root this is an entirely normal Collection subclass """ # note that Collection types are always 'exposed' def __init__(self): """ nothing special here, we can just build a bit of the tree or whatever """ self.hello = hellohandler self.hello.exposed = True def index(self, handler, path, query): """ an exposed method if a URL points to a Collection type, it's 'index' method is used as handler (provided it has one) """ return (200, {'Content-Type': 'text/plain'}, 'index document') index.exposed = True class MyHandler(ObjectPublisherHandler): """ subclassing ObjectPublisherHandler to allow setting an 'application' class variable (singleton) """ application = MyApplication() if __name__ == '__main__': run_server(('', 8080), MyHandler) * BaseHTTPObjectPublisher.Collection The Collection class should be implemented by all container-type resources in the application, including the application root itself. The Collection interface describes a single method, called 'traverse', that is responsible for (recursively) traversing the tree to find a published (exposed) resource handler. It should either return a handler, or raise an HTTPError if something goes wrong. Subclasses can override traverse to change the behaviour of object access, although this will normally not be required. * BaseHTTPObjectPublisher.HTTPError This error can be raised both from handlers and from Collection.traverse to trigger an HTTP response to be generated and presented without further processing. It can be used to indicate errors, for redirection, etc. Note that in the handlers you can choose to either return a status code and body yourself, or raise an HTTPError: the advantage of the latter is that it allows uniform, site-wide error presentation. * BaseHTTPObjectPublished.resource This is a package that contains a number of readily-available resource implementations, such as handlers and collection types that present part of the file system over HTTP, etc. License ======= This code will be released under restrictions of the MIT license. Note that part of the code is taken from the PyPy project, where it is released under the same restrictions.