Interfacing with Angular

Hello,
I’m using: SWI-Prolog version 6.2.2

I would like to interrogate my Prolog program from another language (Angular preferably).
Is their a way to do so ?

Thank you !

1 Like

This is an advanced topic.
See: Foreign Language Interface


You should upgrade to the latest version. Upgrading is not hard.
See:
Install SWI-Prolog development version on Ubuntu using PPA
Install SWI-Prolog development version on Windows
If you need Mac, then I can not help.

Actually I’m avoiding the development version on purpose, but I got the last stable one so I’m on 8.2.1 now.

Thank you. I was looking for a simple way, for example a swi-prolog web service.
It seems to be a bit complicated comparatively to what we would gain to do it.
Thanks !

Glad you added that quip.

This might suit your fancy.
See: Pengines: Web Logic Programming Made Easy

The author @torbjorn.lager hangs out here. He can tell you if this would fit your requirements.

1 Like

Thanks ! That seems to be very interesting, I’ll take a look and contact Torbjörn Lager if it seems to fit our need.

@ILogre, I would definitely use the development version or at least the latest stable. 6.2.2 is way too ancient.

The easiest solution is to use pengines.js, second easiest would be direct HTTP JSON API with CORS (see the http_server module). We don’t seem to have a good minimal “hello world”-type of example tho.

pengines.js is also available on NPM.

1 Like

Interesting approach, but indeed I’m not sure it’s recommended in our case.
Translating the Prolog program into Angular would be one thing (although it seems it’s not offered yet), but it would probably impact performances in a significant way.
Thank you for the suggestion :wink:

I upgraded to 8.2.1 as said earlier :wink:

I can’t find a “http_module” on the CORS reference page (Cross-Origin Resource Sharing (CORS) - HTTP | MDN).
Is the http_module a way to define a web server encompassing my Prolog program ?

Thank you for your suggestions, I’ll be sure to try Pengines.js first

There is a tutorial on web programming by Anne Ogborn at http://www.pathwayslms.com/swipltuts/html/index.html. Might not handle all of this, but it should give a starting point.

1 Like

The tutorial is slightly out of date … I was going to update it but haven’t got around to it.
One item: https://www.swi-prolog.org/pldoc/doc/\_SWI\_/library/http/index.html

For simplicity, you can use library(http/http_server), which combines the typical HTTP libraries that most servers need.

There’s also http://tau-prolog.org/ (Prolog interpreter in JavaScript).

1 Like

I’m sorry, the link seems to be broken.
I am really interest by a “template” or an example of a Prolog http server.

https://www.swi-prolog.org/pldoc/man?section=httpserver

Most server implementation simply load the library(http/http_server) library, which loads the above modules and reexports all predicates except for those used for internal communication and older deprecated predicates. Specific use cases may load a subset of the individual libraries and may decide to replace one or more of them.

And skeleton code is also given.

There’s similar text at https://www.swi-prolog.org/pldoc/doc/_SWI_/library/http/index.html (which Discourse seems to have messed up, so I’ve quoted it here).

2 Likes

Thank you all for your answers !

I will be sure to check Pengines, CORES and HTTP_Server.
If you have some qualitative feedback about the relative difficulties of these solutions, I’d be curious to know !

To provide some context, our problematic is quite simple :
We are working on a class of problems usually tackled by a specific engine type.
In our project, we are wondering is our elements could be seen as a sub-type of the classical problem.
We would like to isolate a part of the classical engine behavior to develop it in Prolog, and then expose this behavior as a web service to be interrogated from external websites.
So our requirements in terms of web server are quite low :

  • expose a handful of functionalities (/services)
  • wrap up the Prolog server with Docker to be deployed on a server.

It won’t be an intensive use, we won’t need persistence, nor to maintain sessions.
So if you experienced with one or several of these solutions, do not hesitate to share your feedback !

With Pengines you might find the work of @sam.neaves of interest.

See: Explorations in Logic Programming for Bioinformatics

1 Like

If the web API is fairly simple and stable I’d simply go for the core SWI-Prolog web libraries. You can use the openapi package to define the API using the OpenAPI 3 specs and generate the server skeleton. That can be worthwhile if the API is large and complex and may be changed frequently. Note that this package is rather experimental. It certainly has bugs dealing with corner cases of the OpenAPI spec.

Pengines are notably interested if you want to upload programs to the server or you want to maintain/develop the programs you want to maintain using SWISH. Using SWISH you can develop and debug a program using the SWISH web interface, save it and use a Pengines client to run the saved program with given parameters. Pengines are less attractive if short response times are critical: you should add a couple of milliseconds the server needs to create a pengine and load the code into it.

1 Like

I’ve been teaching myself WebSocket, and I’d say these days it’s the best way to glue just about any languages together.

For SWI Prolog, setting up a WebSocket server is nearly identical to an http server. The only additions are importing library(http/websocket) and modifying the second argument of http_handler (+Path, :Closure, +Options) to be inside http_upgrade_to_websocket (:Goal, +Options, +Request).

A simple ping-pong example (the “Hello World” of concurrent programming) looks like this on the SWI Prolog side:

:- use_module(library(http/websocket)).
:- use_module(library(http/http_server)).
:- use_module(library(http/http_unix_daemon)).

:- initialization http_daemon.

:- http_handler(root(ws), http_upgrade_to_websocket(loop, []), [spawn([])]).

loop(Request) :-
  ws_receive(Request, Message, [format(json)]),
  (  Message.data.request == "close"
  -> ws_send(Request, close(1000, "normal"))
  ;  request(Message.data.request, Message.data, Reply),
     ws_send(Request, json(Reply)),
     loop(Request)
  ).

request("ping", _Dict, json{reply: pong}).

and would be started on a Linux machine like

swipl server.pl --port=6455 --pidfile=http.pid

where I picked the port number in honour of WebSocket’s RFC number.

Edit to the above code: Following a tip from @jan in the comments below, I added library(http/http_server) to the import list. It imports library(http/http_dyn_workers) which is a better way of setting the number of threads than the --workers=4 in the shell command I originally used.

I’ve never used Angular, but assume the plain vanilla JavaScript code below would work:

const prologServer = new WebSocket("ws://localhost:6455/ws");

prologServer.addEventListener("open", function(event) {
  prologServer.send(JSON.stringify({"request": "ping"}));
});

prologServer.addEventListener("message", function(event) {
  document.querySelector("#message").innerText = JSON.parse(event.data).reply;
});

prologServer.addEventListener("close", function(event) {
  prologServer.close();
});

window.addEventListener("unload", (event) => {
  prologServer.send(JSON.stringify({"request": "close"}));
});

I basically got into WebSocket by experimenting with getting Erlang and SWI Prolog to interface which I put examples of on github showing using SWI Prolog as a server and Erlang as a client, and vice versa.

This style of programming, sending messages in JSON which SWI Prolog handily converts into a dictionary for easy reference (though one gotcha is the value is a string which needs to be translated into something manipulable) and then back, is very Erlangish. Known as the actor model, it took me a bit of getting used to, but I’ve become a fan.

Though very easy when the URL is ws://localhost:portnumber, getting it to work on a public server where browsers insist on wss://samedomainname.com:portnumber is something I’m currently bashing my head against, learning far more about nginx configuration files than I ever wanted to.

2 Likes

Thanks for sharing.

This is a bit old. New code better use library(http/http_dyn_workers) or load all server basics using library(http/http_server).

On public ports some browsers insist on https (wss). If you use nginx as proxy you need something like below. This rule is from SWISH. The first two lines (resolver and proxy_pass) are there to find the lxc container in which SWISH runs and probably needs adapting.

        location /chat {
                resolver 10.0.3.1;
                proxy_pass http://$container$request_uri;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_read_timeout 86400;
        }
1 Like

simpelst is to set up de swi- http server, then test that you can output data on http requests, then let the output be in JSON for example, then in Angular you can make ajax http calls, receive the data and let it parse and use the data

1 Like