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