Prolog Web Applications


Prolog is extremely well suited for developing web applications. Web pages are naturally represented as Prolog terms and can be easily created, inspected and processed recursively.

We distinguish between client and server applications. This page explains in more detail how to use Prolog for these tasks.

Support for web development differs between Prolog systems. At the most basic level, a few simple predicates that let you access network streams would suffice to build rudimentary web applications. Of course, the most widely used Prolog systems typically go far beyond this and ship with more thorough and high-level support for such applications. For example, SICStus Prolog and several other systems ship with the PiLLoW library for WWW programming. In SICStus, it is available as library(pillow).

In the following, we use SWI-Prolog as an example of a Prolog dialect with excellent capabilities for web applications.

HTTP Clients

Fetching pages

A client fetches pages from a server. Using SWI-Prolog, we can easily fetch a page via HTTP and HTTPS using http_open/3.

Example:
?- use_module(library(http/http_open)).
true.

?- http_open('https://www.metalevel.at/prolog', Stream, []).
Stream = <stream>(0x1cadaf0,0x1cad920).
    
This opens Stream for reading the page. The third argument of http_open/3 is a list of options that we can use to obtain header fields and control various aspects of the connection.

Since the https scheme was specified in the example above, a secure connection is automatically established and used. You can use library(ssl) to establish secure connections explicitly.

Parsing HTML

Once we obtain a stream handle for a web page, we can read the page in several ways. For example, we can read one character at a time or use a DCG to process the stream in a pure way.

Very often, it is most convenient to convert the HTML page to a Prolog term that reflects the page structure in a uniform way. The predicate load_html/3 performs this conversion:
?- http_open('https://www.metalevel.at/prolog', Stream, []),
   load_html(stream(Stream), DOM, []).
Stream = ...,
DOM = [element(html, [], [element(head, [], [element(title, ...)])])].
    
See library(sgml) for more information, and related predicates for parsing markup languages like XML.

Processing HTML

Plain Prolog already makes it extremely convenient to process such a nested list of SGML elements, where each element is represented as element(Name, Attributes, Content). We could simply process such structures recursively, using built-in Prolog features.

Amazingly, we can do even better: In SWI-Prolog, library(xpath) allows us to access HTML elements by XPath specifications in a straight-forward way.

For example, let us obtain the text of all list items that appear on a page, in continuation of the previous example:
?- use_module(library(xpath)).
true.
      
?- http_open('https://www.metalevel.at/prolog', Stream, []),
   load_html(stream(Stream), DOM, []),
   xpath(DOM, //li(text), Item).
Stream = ...,
DOM = ...,
Item = 'Introduction' ;
Stream = ...,
DOM = ...,
Item = 'Facets of Prolog' ;
Stream = ...,
DOM = ...,
Item = 'Basic Concepts' ;
Stream = ...,
DOM = ...,
Item = 'Data Structures' ;
etc.
    
On backtracking, all solutions are reported.

HTTP Servers

SWI-Prolog makes it extremely easy to write HTTP and HTTPS servers.

To get started, consider a very rudimentary HTTP server:
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_unix_daemon)).

:- http_handler(/, handle_request, []).

handle_request(_Request) :-
    format("Content-type: text/plain~n~n"),
    format("Hello!").
    
The snippet uses the HTTP Unix daemon library to implement a server that simply responds with Hello! to every request. This library implicitly augments your code with options that you can use on the command line.

To run the server, copy the snippet to server.pl and find out more with:
swipl server.pl --help
    
For example, you can start the server on port 3040 using:
swipl server.pl --port=3040 --interactive
    
Once the server is running, you can test it by browsing to http://127.0.0.1:3040.

In a more realistic HTTP server, the response will of course depend on the actual request of the client. The server libraries represent the parsed request as a list of Name(Value) elements, which can be easily processed in Prolog.

Using different or additional http_handler/3 directives, you can change the behaviour of the server. For example, to serve files from the current directory, use the following directives instead:
:- use_module(library(http/http_files)).
:- http_handler(root(.), http_reply_from_files('.', []), [prefix]).
    
To emit HTML pages, you have several options: Depending on the task, some of these options will be more appropriate than others.

See the HTTP server libraries for more information.

To run a Prolog-based HTTPS server, see LetSWICrypt.

Proloxy is a Prolog-based proxy that uses extensible Prolog clauses for flexible configurations.

Client/Server Applications

Pengines allow us to implement powerful client/server applications in Prolog.

Using Pengines, you can query a remote Prolog server as if it were local, using its results in client Prolog programs or web pages with JavaScript.

For example, consider again the animal identification task described in Expert Systems. We can implement it as a client/server application with: Importantly, the application logic resides completely on the server.

See RITS for an example of a more complex application.


More about Prolog


Main page