# Simple Prolog server with JavaScript client

**URL:** <https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898>\
**Category:** Nice to know\
**Created:** [September 9, 2020, 1:17am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898 "2020-09-09T01:17:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 9, 2020, 1:17am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/1 "2020-09-09T01:17:20Z")

</div>

I’ve written a simple sample client server at

> **[kamahen/swipl-server-js-client](https://github.com/kamahen/swipl-server-js-client)**
>
> Sample SWI-Prolog server with JavaScript client. Contribute to kamahen/swipl-server-js-client development by creating an account on GitHub.

This is intended to supplement the existing documentation and tutorial (basically, it has the skeleton server I wrote while puzzling out some details in the documentation).

The documentation is still a bit rough; any suggestions or PRs will be gratefully accepted. And I would also appreciate being told of any design errors.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 9, 2020, 9:33am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/2 "2020-09-09T09:33:21Z")

</div>

Nice. 🙂

I like the use of [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) and addressing [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing).

Thanks for finding all of the debug/1 options, e.g. `debug(cookie).`

I was planning on trying a callback to the SWI-Prolog server for use with [Cytoscape.js](https://swi-prolog.discourse.group/t/wiki-discussion-generating-cytoscape-js-graphs-with-swi-prolog/2816/4) so will definitely be looking at your code with a fine tooth comb. Will give feedback as I find it.

* * *

The first bit of feedback is the choice of license.

I find that most JavaScript examples have a MIT license ([ref](https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses)) and the SWI-Prolog uses Simplified BSD license ([ref](https://www.swi-prolog.org/license.html))

* * *

While the GitHub page notes how to use it with SWI-Prolog on Ubuntu it also works on Windows 10.

> **Details**
>
> From DOS prompt
> 
> ```dos
> Microsoft Windows [Version 10.0.19041.450]
> (c) 2020 Microsoft Corporation. All rights reserved.
> 
> C:\Users\Groot>cd "C:/Users/Groot/Documents/swipl-server-js-client"
> 
> C:\Users\Groot\Documents\swipl-server-js-client>swipl simple_server.pl --port=9999 --staticdir=static
> % static dir: static
> % Started server at http://localhost:9999/
> % Starting REPL ...
> ?-
> % [Thread httpd@9999_5] [1] get / ...
> % [Thread httpd@9999_5] [1] 302 moved_temporary(/static/simple_client.html); 394 bytes
> % [Thread httpd@9999_1] [2] get /static/simple_client.html ...
> % [Thread httpd@9999_1] [2] 200 file(text/html,c:/users/groot/documents/swipl-server-js-client/static/simple_client.html); 2,084 bytes
> % [Thread httpd@9999_2] [3] get /static/simple_client.css ...
> % [Thread httpd@9999_2] [3] 200 file(text/css,c:/users/groot/documents/swipl-server-js-client/static/simple_client.css); 40 bytes
> % [Thread httpd@9999_2] [4] get /static/simple_client.js ...
> % [Thread httpd@9999_2] [4] 200 file(text/javascript,c:/users/groot/documents/swipl-server-js-client/static/simple_client.js); 4,161 bytes
> % [Thread httpd@9999_2] [5] get /static/favicon.ico ...
> % [Thread httpd@9999_2] [5] 200 file(image/x-ico,c:/users/groot/documents/swipl-server-js-client/static/favicon.ico); 32,038 bytes
> % [Thread httpd@9999_5] [6] post /json ...
> % [Thread httpd@9999_5] [6] 200 OK (0.016 seconds; 20,168 bytes)
> % [Thread httpd@9999_4] [7] post /json ...
> % [Thread httpd@9999_4] [7] 200 OK (0.000 seconds; 1,811 bytes)
> % [Thread httpd@9999_1] [8] post /json ...
> % [Thread httpd@9999_1] [8] 200 OK (0.000 seconds; 20,168 bytes)
> 
> ```
> 
> Using Microsoft Edge
> 
> ![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/0/05597b9bd7aaa12725bc6b5831e95574fabeb528.png)

* * *

For those looking to start the code from the Prolog top level, so they can use make/0 and such, here is a modified predicate

> **Details**
>
> ```prolog
> simple_server_main(Opts0) :-
> dict_create(Opts, opts, Opts0),
> assert_server_locations(Opts),
> http_server([port(Opts.port), workers(5)]),
> debug(log, 'Starting REPL ...', []),
> prolog. % REPL - terminated with exit.
> 
> ```
> 
> Don’t forget to export the predicate:
> 
> ```prolog
> :- module(simple_server,[
> simple_server_main/0,
> simple_server_main/1,
> simple_server_main2/0
> ]).
> 
> ```
> 
> Example run:
> 
> ```prolog
> Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.7)
> 
> ?- working_directory(_,'C:/Users/Groot/Documents/swipl-server-js-client').
> true.
> 
> ?- [simple_server].
> true.
> 
> ?- simple_server_main([port(9999),staticdir(static)]).
> % static dir: static
> % Started server at http://localhost:9999/
> % Starting REPL ...
> % Break level 1
> [1] ?- 
> % [Thread httpd@9999_3] [1] get /static/simple_client.html ...
> % [Thread httpd@9999_3] [1] 304 not_modified; 0 bytes
> % [Thread httpd@9999_3] [2] get /static/favicon.ico ...
> % [Thread httpd@9999_3] [2] 200 file(image/x-ico,c:/users/groot/documents//swipl-server-js-client/static/favicon.ico); 32,038 bytes
> % [Thread httpd@9999_4] [3] post /json ...
> % [Thread httpd@9999_4] [3] 200 OK (0.000 seconds; 141 bytes)
> 
> ```

---

<div class="post-metadata">

**Author:** ![rla](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rla/32/6863_2.png) [@rla](https://swi-prolog.discourse.group/u/rla)\
**Post date:** [September 9, 2020, 9:54am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/3 "2020-09-09T09:54:17Z")

</div>

Thanks for this code! A simple self-contained SWI-Prolog HTTP API example has been asked many times.

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 10, 2020, 11:05am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/4 "2020-09-10T11:05:14Z")

</div>

i have installed it, I appreciate it a lot. This library: http/authenticate and the library: persistent should be added to be able to do the most simple and secure pop-up http authentication and to save the additional user-data data in the persistent prolog db. the main draw back of using ODBC with a database is that many odbc tools do not have the database Create option ( has to be created by db manager tools )

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 10, 2020, 4:30pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/5 "2020-09-10T16:30:03Z")

</div>

I don’t want to complicate my example with non-essential things. But if the authentication and persistence stuff can be added as a separate piece (e.g., an additional handler, or a single line added to an existing handler), then please send a PR or diff.

(I didn’t include SSL support because I gave up after 5 minutes and I don’t need it right now. If someone has a simple “how to” for that, I’d like to add SSL.)

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 10, 2020, 7:10pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/6 "2020-09-10T19:10:02Z")

</div>

i can show you the SSL example because i have 1 linux server that is running with swi-prolog and ssl succesfully for a few months. it is ridiculously simple, it is only 1 line which calls the sll with 2 key files, this the swi-prolog code which i use and which is running :

```prolog
server(Port) :-
   http_server(http_dispatch, [port(Port),
      ssl([
         certificate_file('/etc/apache2/certificate/certificate.crt'),
         key_file('/etc/apache2/certificate/private.key')
      ])
   ]).

```

you can obtain the key files here: [https://www.sslforfree.com](https://www.sslforfree.com)

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 10, 2020, 7:26pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/7 "2020-09-10T19:26:44Z")

</div>

My problem is that I don’t know how to create the certificates, and my attempt to follow the documentation failed (this was a few months ago, so I forget where I found the documentation or what commands I tried). On Linux, of course. And I don’t have a specific domain to secure; I just wanted to run SSL to [http://localhost](http://localhost) for testing.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [September 10, 2020, 7:30pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/8 "2020-09-10T19:30:20Z")

</div>

The ones that [Discourse.com](http://Discourse.com) uses are from [Let’s Encrypt](https://letsencrypt.org/) and they can be configured for automatic renewal. They also have a Discourse [forum](https://community.letsencrypt.org/) for Q&A.

No promises, but I will take a look at this in the next few days as I too would like to see this work. 🙂

* * *

**EDIT**

As I don’t have a Mac I will not be able to do such.  
I can to Windows and Linux via WSL 2.

> **Personal notes**
>
> [How to test secure (https) services from localhost](https://medium.com/47billion/how-to-work-with-https-on-localhost-7f1d2a11be6)  
> [mkcert](https://github.com/FiloSottile/mkcert#mkcert) is a simple tool for making locally-trusted development certificates. It requires no configuration.  
> [How to add a trusted CA certificate to Chrome and Firefox](https://www.techrepublic.com/article/how-to-add-a-trusted-certificate-authority-certificate-to-chrome-and-firefox/)  
> StackOverflow Q&A: [Getting Chrome to accept self-signed localhost certificate](https://stackoverflow.com/questions/7580508/getting-chrome-to-accept-self-signed-localhost-certificate)

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 11, 2020, 3:06am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/9 "2020-09-11T03:06:30Z")

</div>

I’ve added Issues for changing the license and adding SSL.

Please file additional issues at [https://github.com/kamahen/swipl-server-js-client/issues](https://github.com/kamahen/swipl-server-js-client/issues)

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 11, 2020, 8:02am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/10 "2020-09-11T08:02:23Z")

</div>

I have tried too in the past several times to make ssl operational on Localhost, I didnt succeed in this. After that i made de javascript conditional so that on localhost it reads everything from another port, javascript can check wether you are on localhost or not.

---

<div class="post-metadata">

**Author:** ![rla](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rla/32/6863_2.png) [@rla](https://swi-prolog.discourse.group/u/rla)\
**Post date:** [September 11, 2020, 12:12pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/11 "2020-09-11T12:12:21Z")

</div>

To make ssl working on localhost you need to map 127.0.0.1 to some non-“localhost” domain. For example, if your live environment is [example.com](http://example.com), then just add to `/etc/hosts`:

```prolog
127.0.0.1 example.com

```

and use your live cert files.

After you finish development, you can comment out the line (add `#` to the beginning).

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 11, 2020, 1:32pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/12 "2020-09-11T13:32:39Z")

</div>

ok that is a great solution if it works, i will certainly try this

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 11, 2020, 1:57pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/13 "2020-09-11T13:57:26Z")

</div>

You can also simply make a self-signed certificate. The only drawback is that the client you want to use must be told to accept this. Some browsers make this pretty hard. On Firefox you get some seriously looking warnings, but you can quite easily say you know what you are doing.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 13, 2020, 1:07am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/14 "2020-09-13T01:07:30Z")

</div>

> [@EricGT](#):
>
> I find that most JavaScript examples have a MIT license ([ref](https://developer.mozilla.org/en-US/docs/MDN/About#Copyrights_and_licenses)) and the [SWI-Prolog](https://www.swi-prolog.org/pldoc/doc_for?object=manual) uses Simplified BSD license ([ref](https://www.swi-prolog.org/license.html))

I’ve changed the license to simplified BSD - I presume there’s no need to mention MIT. (I was just copying another license I had used, for some different software).

If I’ve done anything wrong, please re-open the [issue at github](https://github.com/kamahen/swipl-server-js-client/issues/1).

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 23, 2020, 12:38pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/15 "2020-09-23T12:38:44Z")

</div>

I noticed in the code that the swi-server is called with worker(5)

I have another swi- webserver already running which doesnt use this worker(5) code,

my question is: does that mean that without the workers specified, the server operates such that every web-request is only handled when the previous request is succesfully terminated?

so with worker(5) the server will have multi threading, so that it handles several requests simultaniously?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 23, 2020, 1:25pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/16 "2020-09-23T13:25:23Z")

</div>

I think the default is 4 workers. If you use `library(http/http_dyn_workers)`, default loaded by `library(http/http_server)` it will dynamically add new workers if there are requests waiting and terminate workers that have been idle too long, respecting certain scheduling limitations. See the library for details.

And yes, by default it handles requests simultaneously. You can prevent that by setting the workers to 1 and not loading `library(http/http_server)` or disable this by setting http:max\_workers to 1.

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [September 23, 2020, 1:40pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/17 "2020-09-23T13:40:18Z")

</div>

thankyou for the information

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 23, 2020, 4:53pm UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/18 "2020-09-23T16:53:07Z")

</div>

I’ll remove the workers(5) option. It’s not special, compared to the other options. 😉

---

<div class="post-metadata">

**Author:** ![drspro](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/drspro/32/3509_2.png) [@drspro](https://swi-prolog.discourse.group/u/drspro)\
**Post date:** [October 6, 2020, 6:08am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/19 "2020-10-06T06:08:24Z")

</div>

to run the swi http server in general, in old posts it was stated  
that one could use:

:- use\_module(library(http/thread\_httpd)).  
:- use\_module(library(http/http\_dispatch)).

to start the server

in the recent posts I see that

:- use\_module(library(http/http\_server)).

was the way to do it, are these 2 exchangable?

or is the new approach better? the last approach was recommended in the recent posts form this subject

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 6, 2020, 6:40am UTC](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898/20 "2020-10-06T06:40:44Z")

</div>

> [@drspro](#):
>
> was the way to do it, are these 2 exchangable? Or is the new approach better?

After importing the same set of several hard to remember library names over and over and considering the fact that these libraries export several deprecated predicates or predicates that are not even intended for end users I have decided to add library(http/http\_server). It doesn’t do much: just load all the core components of the HTTP server infrastructure and export the stuff that is still considered relevant.

Better? That depends on your perspective. I guess if you just want a standard server the answer should be “yes”. If you want more control (aggressively minimize the footprint, replace components, etc.) the answer is probably “no”.

[Next page](https://swi-prolog.discourse.group/t/simple-prolog-server-with-javascript-client/2898.md?page=2)
