OpO can be extended by HTTP handler applications. Similar in concept to plug-ins but completely isolated from OpO itself. Using the configuration file handlers can be set to process URL paths that match patterns defined in the configuration file. When an HTTP request is made to one of those URLs a JSON request message is created and passed to specified applications over pipes. The applications are forked when needed and can be persistent to handle multiple requests.
The typical flow of messages starts with an HTTP request to the OpO HTTP Server which forms a JSON message and delivers that message to the App over STDIN. This is the (1) API in the diagram. That API is also identified by that value in the message to allow for identification by the application and for debugging.
Responses from the App to the OpO view portion is over the App's STDOUT file descriptor and is identified as the (2) API.
If the App needs data to form a response it uses the same STDOUT file descriptors but identifies the message as an API (3) message. An API (3) message is processed as a request to the OpO model.
Responses from the OpO model to the App use the API (4) exchange and messages over the App's STDIN.
Interrupt messages not directly tied to the flow of a request are also supported. Any negative API value is taken to be the same as a unix interrupt. Receiving a -2, -3, -6, or -15 indicate an orderly shutdown while a -9 is an immediate exit.
Support for logging is accomplished with API message types 5 and 6. API 5 messages are used to notify the App of changes in the logging level while API 6 messages are used to send log entries from the App to OpO.
A similar approach is used for OpO-Rub and the embedded Ruby. See WABuR project for details.