Developing on Commissaire HTTP¶
Commissaire HTTP provides a multithreaded REST interface into Commissaire
functionality. The server is broken up into 5 main parts: Router
,
Dispatcher
, Function Handler
, Class Handler
, and the
CommissaireHttpServer
itself.
Router¶
The Router
maps URI paths to controllers. The following example would route
the path /hello/
to the controller at commissaire_http.handlers.hello_world
if the HTTP method is GET
.
mapper = Router()
mapper.connect(
'/hello/',
controller='commissaire_http.handlers.hello_world',
conditions={'method': 'GET'})
Dispatcher¶
The Dispatcher
uses a Router
and, as it’s name suggests, dispatches
the requests to the proper controller. It also takes care of loading
handlers. The following example creates a new Dispatcher
instance using
a previously created Mapper
. It will load handlers found in the
commissaire_http.handlers
and mypackage.handlers
packages.
dispatcher = Dispatcher(
mapper,
handler_packages=[
'commissaire_http.handlers',
'mypackage.handlers'])
Handlers¶
Handlers
, also called controllers, do the majority of the business logic.
A Handler
can be a function or a class, but must follow a specific
convention so the Dispatcher
knows it’s valid during loading.
Function Handler¶
Function Handlers must take two parameters: message
and bus
. The first
input, message
, is the jsonrpc message. The second input, bus
will
either be a valid connection to the bus or, if the bus is not enabled,
None
.
When referencing a Function Handler as a controller use the full package path
to the function. If the function is hello_world
and it lives under
commissaire_http.handlers
then the controller would be
commissaire_http.handlers.hello_world
.
The following example would show the user {"Hello": "there"}
or
{"Hello", "{{ name }}"}
depending on parameters. Remember, the return of
the handler must be a valid jsonrpc message as well!
Note
The method
in the incoming jsonrpc message is hijacked and filled
with the HTTP method that was used to call the handler.
def hello_world(message, bus):
"""
Example function handler that simply says hello. If name is give
in the query string it uses it.
:param message: jsonrpc message structure.
:type message: dict
:returns: A jsonrpc structure.
:rtype: dict
"""
response_msg = {'Hello': 'there'}
if message['params'].get('name'):
response_msg['Hello'] = message['params']['name']
return {
'jsonrpc': '2.0',
'id': message['id'],
'result': response_msg,
}
Class Handler¶
A Class Handler is not much different than a Function Handler. Instead of
defining a single function, a class is declared with methods that take three
parameters: self
, message
, and bus
. If the method should not be
considered a handler it must start with an underscore.
One major difference between a Class Handler and Function Handler is that Class Handlers are instantiated when they are loaded!
When referencing a Class Handler as a controller, use the full package path
to the class and the method. If the class is ClassHandlerExample
,
the method is hello
, and it lives under commissaire_http.handlers
then the controller would be
commissaire_http.handlers.ClassHandlerExample.hello
.
The following example exposes hello
in the same way as the Function
Handler example above. It then uses hello_world
to do the heavy lifting.
class ClassHandlerExample:
"""
Example class based handlers.
"""
def hello(self, message, bus):
"""
Example method handler that simply says hello. If name is given
in the query string it uses it.
:param message: jsonrpc message structure.
:type message: dict
:returns: A jsonrpc structure.
:rtype: dict
"""
return hello_world(message, bus)
def _ignored(self):
"""
This method would not be loaded as a handler but could be used by
handlers in this class.
"""
return 'I am ignored.'
CommissaireHttpServer¶
In the following example, a CommissaireHttpServer
is created which binds to
address 127.0.0.1 and port 8000 and uses a previously created Dispatcher
. It
then is set to run (block) until killed.
server = CommissaireHttpServer('127.0.0.1', 8000, dispatcher)
server.serve_forever()
Code Example¶
See http_server.