Implement HTTP API for Plugin Communication
We've been exploring options for more flexible and scalable plugin integrations. Based on the discussions and a demo shared by @lainz in https://github.com/bgrabitmap/lazpaint/issues/553#issuecomment-1752176751, we're leaning towards implementing an HTTP API to facilitate communication between LazPaint and various plugins.
Currently scripts have their own Script menu. For starters, we can use this menu to access plugins, but maybe we could rename it at some point.
- plugin configuration: it will be possible to configure a plugin via a menu item
Plugin/script configuration.... Either by specifying a URL or by looking up an html file (a Python file will be possible as well and may also be implemented by https://github.com/bgrabitmap/lazpaint/issues/553). The name of the plugin can be retrieved from the page or file. For an html page, the title tag contains a probable name. It will be possible to customize the name of the plugin. - API port configuration: the port shall be configurable in the menu like
Set API port...or from the dialog boxPlugin/script configuration
The plugin invocation via the menu would have the following steps:
- user clicks the plugin item
- the API server is created and LazPaint starts awaiting (it closes the tool windows)
- the URL is opened (a token could be provided as URL parameter for security and to be sure to differentiate if a previous plugin is still sending requests at the same time)
- the plugin invokes an API to confirm it is running (otherwise after 10 seconds, it is considered as timeout) with URL
/api/beginwith token as parameter - the plugin in the webpage invokes the API as needed
- when the plugin is closed, it invokes an API to notify the end of the plugin (this can be done by binding
window.onbeforeunloadevent) with URL/api/endwith token as parameter - the API server is closed and LazPaint stops awaiting (it reopens the tool windows and do some clean up)
One thing to consider is how to close the plugin if it never notifies via the API that it finishes. Same applies in fact to Python scripts, though in this case, one can close or kill Python task. This is not possible with a waiting API. Another approach is to require the plugin to notify it is still open every 10 seconds.
The API would provide, on top of the specific functions related to web plugin invocation, the usual scripting functions, the path of the URL being /api/ followed by the name of the function and the parameters provided via POST object parameter in JSON. The token would be an additional parameters. The case of the variables may change to make it more web-like ("spinal-case" case instead of Pascal case for function names and parameters).
The scripting results would be mapped to http codes as following:
-
srOk: If there's a value returned: HTTP 200 OK. If no value returned: HTTP 204 No Content -
srInvalidParameters: HTTP 400 Bad Request -
srFunctionNotDefined: HTTP 404 Not Found -
srCancelledByUser: HTTP 409 Conflict -
srException: HTTP 500 Internal Server Error
Additionally the URL / or /index.html could return a page saying the server is running and list the available functions.
Maybe a Json file can be used to retrieve plugin information. Name (for each language), author, version, website, email...
Yes, that could be a file next to the webpage.