# Yet another web applications tutorial

**URL:** <https://swi-prolog.discourse.group/t/yet-another-web-applications-tutorial/566>\
**Category:** Announce\
**Created:** [April 21, 2019, 3:31pm UTC](https://swi-prolog.discourse.group/t/yet-another-web-applications-tutorial/566 "2019-04-21T15:31:39Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![joeblog](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/joeblog/32/122_2.png) [@joeblog](https://swi-prolog.discourse.group/u/joeblog)\
**Post date:** [April 21, 2019, 3:31pm UTC](https://swi-prolog.discourse.group/t/yet-another-web-applications-tutorial/566/1 "2019-04-21T15:31:39Z")

</div>

While teaching myself how to develop a web application with SWI-Prolog, I’ve taken notes for future reference, which others may find useful since I’ve had to figure much of this out through trial and error.

My tutorial differs from Anne Ogborn’s at [http://www.pathwayslms.com/swipltuts/html/index.html](http://www.pathwayslms.com/swipltuts/html/index.html) in that I’ve not used the html\_write library (I’m ideologically opposed to templating), and have gone in directions I personally found initially difficult to grasp from the documentation (though which turned out to be very simple once I went aha!).

I’ve put my progress so far here for any suggestions or corrections. I don’t think it’s suitable for [https://swish.swi-prolog.org](https://swish.swi-prolog.org) since I assume one can’t run server code on it, so any suggestions for a good place to make it available once complete would be appreciated.

# Step 1: Creating a simple SWI-Prolog web server

```prolog
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_unix_daemon)).
:- use_module(library(http/http_files)).

:- multifile http:location/3.
http:location(files, root(files), []).
user:file_search_path(folders, library('images/styles/scripts')).

:- http_handler(root(.), http_reply_from_files('.', []), [prefix]). % defaults to index.html
:- http_handler(files(.), serve_files_in_directory(folders), [prefix]).

:- initialization http_daemon.

```

The lines of prolog above in a file called server.pl create a web server which can be started with, say:

```prolog
swipl server.pl --port=3030 --pidfile=http.pid

```

and stopped with:

```prolog
kill $(cat http.pid)

```

Assuming there is an index.html file in the same directory as server.pl and its associated files are in subdirectories called images, styles, and scripts, simply point your browser to [http://localhost:3030/](http://localhost:3030/)

One of the many advantages of serving static files rather than programmatically generated output is you can start with a skeleton index.html file,  
say:

```prolog
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Page Title</title>
  <link rel="stylesheet" href="/styles/mystyle.css">
</head>
<body>
  <p>Hello World!</p>
  <script src="/scripts/myscript.js"></script>
</body>
</html>

```

and then see your site develop by simply refreshing your browser as you edit and add files without needing to constantly start and stop the server —  
unless you add handlers by editing in the server.pl file, as in the next section.

If you’re new to html coding or need a refresher, I suggest Mozilla’s  
[Getting started with the Web](https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web).

# Step 2: Advancing to AJAX

Since I last worked through developing a simple web application, the Javascript world has moved on a lot, with [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) simplifying the verbose syntax still used in  
Mozilla’s [getting started](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started) with [Ajax](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX) tutorial.

I’ve added a handler linked to url /test in server.pl called test\_handler which receives a Json object ‘{“userName”: _some value_}’.

Using library(http/http\_json)'s http\_read\_json\_dict/2, the value of userName is read, prefixed with "Hello, " and then returned housed in a Json object with key computedString.

This is hopefully sufficient to demonstrate how simple it is to use Ajax and Json with a SWI-Prolog server.

```prolog
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_unix_daemon)).
:- use_module(library(http/http_files)).
:- use_module(library(http/http_json)).

:- multifile http:location/3.
http:location(files, root(files), []).
user:file_search_path(folders, library('images/styles/scripts')).

:- http_handler(root(.), http_reply_from_files('.', []), [prefix]). % defaults to index.html
:- http_handler(files(.), serve_files_in_directory(folders), [prefix]).
:- http_handler('/test', test_handler, []).

test_handler(Request) :-
  member(method(post), Request), !,
  http_read_json_dict(Request, _{userName:NameIn}),
  string_concat("Hello, ", NameIn, NameOut),
  reply_json_dict(_{computedString:NameOut}).

:- initialization http_daemon.

```

I’ve updated Mozilla’s beginner example to [use fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)  
instead of XMLHttpRequest in a file called main.js in the scripts subdirectory:

```prolog
(function() {

  document.getElementById("ajaxButton").onclick = function() { 
      var userName = document.getElementById("ajaxTextbox").value;
      makeRequest('/test', userName); 
  };

  function makeRequest(url, userName) {
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({"userName": userName})
    })
    .then(res => res.json())
    .then(response => alert(response.computedString))
    .catch(error => alert('Caught Exception: ' + error.description));
  }

})();

```

and the index.html file looks like this:

```prolog
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Ajax 1</title>
  <link rel="stylesheet" href="/styles/basic.css">
</head>
<body>
  <label>Your name: 
    <input type="text" id="ajaxTextbox" />
  </label>
  <span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
    Make a request
  </span>
  <script src="/scripts/main.js"></script>
</body>
</html>

```

# Step 3: Linking the server to a database (Postgresql in this example).

This is still work in progress. For the impatient, here’s the start of the next  
section:

SWI-Prolog communicates with Postgres via the [ODBC Interface](http://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/odbc.html%27)).

Getting this to work requires having the [PostgreSQL ODBC driver](https://odbc.postgresql.org/) installed and an ~/.odbc.ini file. Details are at [http://www.unixodbc.org/odbcinst.html](http://www.unixodbc.org/odbcinst.html)

NOTE: MaxVarcharSize = 500 (or bigger) is needed, else ODBC truncates strings at 255 as explained at [https://odbc.postgresql.org/docs/config.html](https://odbc.postgresql.org/docs/config.html)

```prolog
[postgresql]
Description = Test to Postgres
Driver = /usr/lib/psqlodbcw.so
Trace = Yes
TraceFile = sql.log
Database = games
Servername = localhost
UserName = my_username
Password = my_password
Port = 5432
Protocol = 9.4
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ShowOidColumn = No
FakeOidIndex = No
ConnSettings =
MaxVarcharSize = 500

```

Queries via SWI-Prolog can then be done like so:

```prolog
/*
roblaing=> select * from accounts;
 owner | balance | amount 
-------+---------+--------
 Mary | 214.00 |       
 Bob | 86.00 |       
*/

:- use_module(library(odbc)).

dbquery(Owners) :-
  odbc_connect('postgresql' , Connection, []),
  odbc_query(Connection, 'SELECT owner FROM accounts', Owners, [findall(Owner, row(Owner)]),
  odbc_disconnect(Connection).

```

---

_[View the full topic](https://swi-prolog.discourse.group/t/yet-another-web-applications-tutorial/566)._
