Creating Webpages with SWI-Prolog and PWP: Handling Assets

Introduction

This is part four in the series, Creating Webpages with SWI-Prolog and PWP.

The previous lesson in this series showed how to create a basic server in prolog that serves up a PWP page. In this lesson, you will learn how to handle additional URLs and serve up other types of files including images, css and javascript.

Getting Started

Start with the server.pl from Starting a Server. In this version of the server, http_handler is used to serve up a PWP page (index.pwp) whenever anyone visits the root of the website (For example, when visiting: http://localhost:8000/.) However, a “Not Found” error returned for every other path under that domain, including http://localhost:8000/index.pwp. This is because we never provided any rules for how to deal with paths besides /.

This can be done by adding rules to handle more files. For this lesson, we will modify the server to be able to handle the following:

  • CSS files
  • Javascript files
  • Image files

Start by setting up additional copies of http_handler for the /js, /css, and /images directory and have these direct to an assets_handler you will add next.

:- http_handler('/js', assets_handler, [prefix]).
:- http_handler('/css', assets_handler, [prefix]).
:- http_handler('/images', assets_handler, [prefix]).

 
Note that these handlers differ slightly from the default handler, by also setting the prefix option. prefix tells the handler that any URL that begins with that string should be handled by the handler (example: ‘/js’ matches both ‘/js/script.js’ and /js/jquery.js’).

Next, add the code for assets_handler.

assets_handler(Request):-
	memberchk(path(Path),Request),
	http_reply_file(root(Path),[],Request).

 
This handler gets the actual path from the Request header information and supplies it to the http_reply_file/3 predicate. Note that this is using the value root(Path), not just Path. root() is the file search path that tells prolog where in the filesystem to find that file. Before this will function properly, a root file search path must be set up. Add the following line above the http_handlers.

user:file_search_path(root,'.').

 
That’s it! The final server.pl file should look like:

% include some libraries
:-use_module(library(http/thread_httpd)).
:-use_module(library(http/http_dispatch)).
:-use_module(library(http/http_pwp)).

user:file_search_path(root,'.').

% setup a handler to tell prolog what to do when the user visits an assets directory
% prefix matches anything that starts with the supplied string.
:- http_handler('/js', assets_handler, [prefix]).
:- http_handler('/css', assets_handler, [prefix]).
:- http_handler('/images', assets_handler, [prefix]).

% setup a handler to tell what prolog to do when the user visits anything under /
:- http_handler(/, default_handler, []).

% predicate to start the server
server(Port):-

	% start server on specified port
	http_server(http_dispatch, [port(Port)]).

% predicate to handle assets directories
assets_handler(Request):-

	% file is not PWP
	memberchk(path(Path),Request),
	http_reply_file(root(Path),[],Request).

% Used by http_handler to determine what to do when handling the HTTP request
default_handler(Request):-

	% display index.pwp
	reply_pwp_page('index.pwp',[],Request).

 
Go ahead and create an index.pwp file and be sure to include links to files in /css, /js, and /images. Go to the interactive swipl console and start the server and then visit http://localhost:8000 to test the page.

?- consult(server).
?- server(8000).

 
Check back soon for a new tutorial on Creating Webpages with SWI-Prolog and PWP: Bootstrap Example.