Providing HTTP Services with Prolog

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.

Providing HTTP Services with Prolog
Starting the HTTP server

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

Providing HTTP Services with Prolog
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:

Providing HTTP Services with Prolog
Hello World Response

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:

Providing HTTP Services with Prolog
Atoms and Strings are Not Equal

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

Leave a Comment