Two possibilities:
Observer pattern: plugins will register themselves and listen to signals. Plugins will receive the request/response objects and they will be able to manipulate them:
FCGI application starts and maintain an hash of services exposed by the plugins
When FCGI loop ends without a match for the core services (WMS, WFS, WCS) the 404 handler matches SERVICE with the service metatag exposed by the plugin.
Example query string:
http://localhost/cgi-bin/qgis_mapserv.fcgi?SERVICE=HELLO&REQUEST=SayHello
Python methods (static!) are invoked and their output is captured and passed on to FCGI
Plugins exposed SERVICE and REQUEST methods are listed in Plugin's metadata:
Example metadata:
service=HELLO methods=GetCapabilities,GetOutput,RemoteConsole,SayHello
When all checks are done the plugin runs by calling the method in the REQUEST, the method receives:
The plugin (static) method has access to global python environment and can run arbitrary python commands, it can optionally return a content type string (the server defaults to text/plain).
The plugin CGI-style output is captured diverting stdout and stderr to a custom buffer which becomes the server response.
@staticmethod
def SayHello(project_path, parameters):
"""Just say something"""
print "HelloServer"
return 'text/plain'
Example response:
200 OK Connection: close Date: Thu, 04 Sep 2014 09:56:36 GMT Server: Apache/2.4.7 (Ubuntu) Vary: Accept-Encoding Content-Length: 12 Content-Type: text/plain Client-Date: Thu, 04 Sep 2014 09:56:36 GMT Client-Peer: 127.0.0.1:80 Client-Response-Num: 1 HelloServer
The current main loop:
create GET/POST/SOAP request handler
else Exception
The new main loop:
create GET/POST/SOAP request handler
pass request to iFace
call plugins (emit request signal)
call plugins (emit 404 signal)
call plugins (emit response signal)
store Exception in the request handler
request handler output the response
Not sure about what should be exposed:
Should we use the same system for desktop and server plugins?
What is the (mostly) unique selling point of QGIS Server ?
GUI-based configuration of the map and the services!
A Server plugin can have (not must) a desktop interface aimed to configure itself
One-click install and deployment
An example plugin is available:
https://github.com/elpaso/qgis-helloserver
A running implementation of the sever plugins basic functionalities is available here:
https://github.com/elpaso/QGIS/tree/serverplugins
Local test:
http://qwc/cgi-bin/qgis_mapserv.cgi?SERVICE=HELLO&request=GetCapabilities http://qwc/cgi-bin/qgis_mapserv.cgi?SERVICE=HELLO&request=SayHello http://qwc/cgi-bin/qgis_mapserv.cgi?SERVICE=HELLO&request=RemoteConsole http://qwc/cgi-bin/qgis_mapserv.cgi?SERVICE=WPS&request=GetCapabilities
If the plugin has a Desktop interface it cannot usually access to user's QSettings, this means that plugins options have to be stored somewhere else in order to be accessible by the server side.