Did you know ... Search Documentation:
Adding application logic to a Pengine server

Any SWI-Prolog web server can be pengine enabled by loading library(pengines) and configuring the access rights. Clients can then create pengines that execute code in the module pengine_sandbox. By default, they can only execute white-listed code as defined by the library(sandbox), i.e., mostly Prolog code that has no side effects.

Typically, a server serves a particular application. This application comes with a particular API. A nice and clean example is the RDF library as realised by library(semweb/rdf_db). If the pengine server wishes to make this library available to pengines, it must import this library into the module pengine_sandbox using the following query:

:- use_module(pengine_sandbox:library(semweb/rdf_db)).

This declaration allows pengines to use the side effect free RDF query predicates, in particular rdf/3.

An application that wishes to provide similar functionality should take the following steps:

  1. Define a module that exports the desired API. Remember that the client can easily add predicates that combine API calls and massage data into a format suitable for the application, so you don't have to think about these application oriented queries. Instead, make your queries general and purely declarative!
  2. Import this library into pengine_sandbox as illustrated above.

That is all, except that library(sandbox) may not like your code. What now? There are several reasons and work-arounds.

The sandbox library does not understand my code
This shows up as instantiation errors and implies that the sandboxing libraries finds meta-calls but cannot determine what will be called. There are two remedies:
  • Make the source easier to track. Avoid some meta-calling by passing terms that indicate what should happen and a static predicate that interprets these terms. This is often a good idea if the intend is to meta-call to a well defined set of predicates.
  • Isolate the most deeply nested bit of code that is safe, regardless how it is called and declare this to be safe using sandbox:safe_primitive/1 or, if it is a meta-predicate, using sandbox:safe_meta/2.
The API calls foreign code
Library(sandbox) cannot prove anything about foreign code. Make sure it is written properly and declare it using sandbox:safe_primitive/1.
The API has side effects, but that it what it should do
Make sure that the API correctly validates arguments and really cannot do anything unintended and declare it using sandbox:safe_primitive/1.