Introduction
Continuing from the previous article, where we attempted to write a Hello World program in Prolog, we learned about the basic structure and execution of Prolog programs. In this article, we will build a simple HTTP server based on <span>hello_world.pl</span>
.
Starting the HTTP Server
Using the built-in library of SWI-Prolog, it is easy to start an HTTP server. You just need to call the function <span>http_server</span>
.
:- initialization(main, main).
:- use_module(library(http/http_server), [http_server/1]).
main(_) :-
http_server([port(8082)]),
sleep(100000000).
Save the above code to a file <span>http_server.pl</span>
and run it to start the HTTP server.

Since no interfaces are defined in the source file, any request will return a 404 response.

Using Modules
The <span>use_module</span>
command mentioned above is a directive used to import functions from a module. For example, <span>:- use_module(library(http/http_server), [http_server/1]).</span>
means importing a function <span>http_server</span>
with one parameter from the module <span>http/http_server</span>
into the current module, allowing it to be called directly.
Providing Interfaces
As mentioned earlier, since the current application has not registered any routing rules, any request will return a 404 response. Next, I will add a very simple interface to this HTTP server that returns the text <span>Hello, world!</span>
. To register an interface, we need to use the function <span>http_handler</span>
from the module <span>http/http_dispatch</span>
. According to its documentation[1], it requires three parameters:
- Interface path
<span>Path</span>
, such as a path represented by an atom<span>/api/shorten</span>
; - The function object responsible for implementing the interface business logic
<span>Closure</span>
; - A list describing the interface properties
<span>Options</span>
, such as the request method for the interface.
An interface that returns the Hello World string might look like this:
:- initialization(main, main).
:- use_module(library(http/http_dispatch), [http_handler/3]).
:- use_module(library(http/http_server), [http_server/1]).
hello(_Request) :-
format('Content-Type: text/html~n~n'),
format('Hello, world!').
main(_) :-
http_handler('/api/shorten', hello, [methods([get])]),
http_server([port(8082)]),
sleep(100000000).
The test results after starting the service in the old way are as follows:

Interface Path
As the first parameter of <span>http_handler</span>
, <span>'/api/shorten'</span>
looks very much like a string familiar in other mainstream languages; however, in Prolog, it is an atom (<span>atom</span>
). Although the content inside the quotes looks the same, atoms and strings are not equal, as shown in the following image:

Interface Output
From the documentation[2] of SWI-Prolog, we know that the second parameter of <span>http_handler</span>
must output at least <span>Content-Type</span>
and the body of the data. Furthermore, although the implementation of <span>hello</span>
seems to output the response content to standard output (in a style reminiscent of ancient CGI scripts), the destination of the <span>format</span>
output has already been replaced by the framework. We can replace it with the following code to better understand this:
:- initialization(main, main).
:- use_module(library(http/http_dispatch), [http_handler/3]).
:- use_module(library(http/http_server), [http_server/1]).
hello(_Request) :-
current_output(Stream),
format(Stream, 'Content-Type: text/html~n~n', []),
format(Stream, 'Hello, world!', []).
main(_) :-
http_handler('/api/shorten', hello, [methods([get])]),
http_server([port(8082)]),
sleep(100000000).
The request results will be the same.
References[1]
Documentation: https://www.swi-prolog.org/pldoc/man?predicate=http_handler/3
[2]
Documentation: https://www.swi-prolog.org/pldoc/man?section=html-body