How to load an image in HTML using Prolog?

Hello, I’m new creating web applications in SWI-Prolog and I tried to load an jpeg image in my web server as the firsts examples in the documentation, but it doesn’t work. I get an 404 error code (image not found) when I run the server, where do I have to save my image to get it loaded? Am I skipping any important segment of code?

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/html_write)). % new

:- http_handler(root(hello_world), say_hi, []).

server(Port) :-
        http_server(http_dispatch, [port(Port)]).

say_hi(_Request) :-
        reply_html_page(title('Hello World'),
                        [ h1('Hello World'),
                          p(['This example demonstrates generating HTML ',
                             'messages from Prolog.','<br>',
                             'This is going to be useful for the proyect.'
                            ]),
                            p(['Another line of code.']),
                            table([ tr([ td('cell 1a'), td('cell 1b')]),
                tr([ td('cell 2a'), td('cell 2b')])
              ]),
              img([width(500),height(300),src('../icons/imagen1.jpeg')])
                        ]).

Learning the details of creating an SWI-Prolog HTTP(S) server can be hard as there are often not many examples.

As such in the Wiki post

Useful Prolog references

is the GitHub section

The following list were hand selected for the exceptional quality of the Prolog code.

With regards to what you seek take a look at

GitHub repositories for SWI-Prolog Ludum Dare Teams

If you use the GitHub search for image (search)

you may find what you seek but more importantly many other useful ideas.

Well, there is swiplwebtut/web.adoc at 07b42b1e7eac000d9eeac959ba2a38a616fd4b9b · Anniepoo/swiplwebtut · GitHub linked from the main web page tutorials. It is a bit old, but a lot is still relevant.

Two quick remarks. Since quite some time there is a single library that imports everything needed by practically every website and only re-exports the generally useful stuff:

:- use_module(library(http/http_server)).

If you want to serve files, you need to tell the server to do so. There are two options. Using http_reply_file/3 you can reply a single file directly from an http_handler/3 declaration. That is as simple as

:- http_handler(root('icons/imagen1.jpeg')),
                http_reply_file('imagen1.jpeg', []), []).

The alternative is http_reply_from_files/3, which allows you to serve a directory of static files from some location. It should probably get some examples.

1 Like

@FernandoHB

That is an excellent set of articles which I did work through in detail a few years ago. IIRC it is no longer being updated and there were some examples that no longer work as demonstrated. The concepts still hold but the details of the code needed some changing to get running with newer versions of SWI-Prolog.

Overall, even with the hazards of the stie, I would still recommend doing the site for anyone trying to learn how to do SWI-Prolog HTTP servers.

Also the other big problems I still have with creating SWI-Prolog HTTPS servers not HTTP servers is using CORS, but that is my problem not the SWI-Prolog code, and trying to set up an HTTPS server on a dev machine when one does not own a domain name.

If you are really adventurous try using ChatGPT to create simple SWI-Prolog HTTP servers of about 100 lines of code. Often the code works or needs little modifications and will often give a different way to write the code that may not be apparent. Note that any such code generated by ChatGPT should be thoroughly vetted and enhanced before using in production.

ChatGPT example (click triangle to expand)

Prompt
ChatGPT May 24 Version

Create SWI-Prolog code for an HTTP server to display a single page containing

  • “Hello World”
  • A table with three columns and four rows
  • A jpeg image from the icons subdirectory

Do not use format/1.

Completion

Sure! Here’s an example of SWI-Prolog code for an HTTP server that displays a single page with the requested elements:

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_files)).
:- use_module(library(http/html_write)).

% Define the HTTP server port
server(Port) :-
    http_server(http_dispatch, [port(Port)]).

% Route for serving the HTML page
:- http_handler(root(.), home_page, []).

% Define the HTML page
home_page(_Request) :-
    reply_html_page(
        title('Hello World'),
        \page_content
    ).

% Define the content of the page
page_content -->
    html([
        h1('Hello World'),
        table([
            tr([th('Column 1'), th('Column 2'), th('Column 3')]),
            tr([td('Row 1 Data 1'), td('Row 1 Data 2'), td('Row 1 Data 3')]),
            tr([td('Row 2 Data 1'), td('Row 2 Data 2'), td('Row 2 Data 3')]),
            tr([td('Row 3 Data 1'), td('Row 3 Data 2'), td('Row 3 Data 3')])
        ]),
        img([src('icons/image.jpg')])
    ]).

% Serve static files from the 'icons' subdirectory
:- http_handler(root(icons), http_reply_from_files('icons', []), [prefix]).

% Start the server on port 8000
:- initialization(server(8000)).

To use this code, make sure you have SWI-Prolog installed on your system. Save the code to a file (e.g., server.pl), and then run it from the SWI-Prolog interpreter using the consult/1 predicate:

?- consult('server.pl').

Once the server is running, you can visit http://localhost:8000 in your web browser to see the page with “Hello World,” the table, and the JPEG image. The image file should be placed in a subdirectory named icons relative to the location of the server script.

Note that this code uses the SWI-Prolog libraries http/thread_httpd for creating the HTTP server, http/http_dispatch for dispatching the requests, http/http_files for serving static files, and http/html_write for generating HTML content.


Note: Did not try to compile and run the code. This is to demonstrate that ChatGPT can create SWI-Prolog HTTP server code that works or is in the ballpark.

1 Like

Pretty impressive! Haven’t tried it, so it may have some mistakes, but it is surely close. As mentioned before, using :- use_module(library(http/http_server)). would be better. This also provides http_server/1. Starting the server using initialization/1 is a bit dubious. Good enough for interactive usage though. This probably illustrates the weakness of ChatGPT to miss relatively recent improvements.

1 Like

5 posts were split to a new topic: LLMs and SWI-Prolog - a few shared thoughts

The sample code at GitHub - kamahen/swipl-server-js-client: Sample SWI-Prolog server with JavaScript client uses this newer API. It includes a handler for serving static files using http_reply_from_files/2, including caching (which requires nothing more than adding a cache(true) option).

1 Like