Prolog and the Web
Home

Modern machines are so fast that using CGI (Common Gateway Interface), the original route between web client and server, is very workable. The great advantage of CGI is that it makes easily possible a wide range of server backend languages. The extremely high-level view of using CGI on HTML pages, say for a button, is this:
    Browser displays page P0 with a button B		[1]
	↓
    User presses the button				[2]
	↓
    CGI action/transition on server produces page P1	[3]
	↓
    Browser displays page P1 				[4]
Two ways this view can be expanded are (1) by embedding button B in a form, and (2) by utilizing Javascrip attached to the button.

(1) Embedding a button B in a form.

The extremely high-level view will expand to
    Browser displays page P0 with a button B		[1]
	↓
    User presses the button				[2]
	↓
    Form action invokes handler "ABC.cgi"		[3]
	↓
    Backend language call(e.g., prolog) returns page P1	[4]
	↓
    Browser displays page P1 				[5]
Below is a simple forms-oriented sample. You can directly run it by pointing your browser at
	https://kabstuff.com/prolog_web/form_sample/
The sample files can be downloaded from: Form-Oriented Sample Files

[1] Consider the file sample.html, containing an HTML date object and a button:
<HTML>
<HEAD>
<title>sample: forms + prolog
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</HEAD>
<BODY>
<h1>sample: forms + prolog</h1>
<form action="form_sample.cgi">
Date: <input type="date" name="seldate" value="2023-05-23">
<button type="submit">Submit Date</button>
</form>
</HTML>
Invoking http://kabstuff.com/prolog_web/form_sample/sample.html, we see page P0:

sample: forms + prolog

Date:

Now when steps [1],[2],[3] are carried out, a stream S (back)to the client browser is passed along. The statment <form action="form_sample.cgi"> defines the form. This sets the handler for the form to be the file form_sample.cgi. [2] When the user presses the button B, the browser submits the form to the web server, which in turn invokes the handler form_sample.cgi, thereby executing form_sample.cgi in a manner similar to the way the OS invokes shell files.
[3] Here is the file form_sample.cgi:
#!/bin/bash
#################################################################
##### form_sample.cgi
##### NOTE: This file must be executable
#################################################################
#echo 'Content-Type: text/plain'
echo 'Content-Type: text/html'
echo
#For pedagogy, print msg when no query:
if [ -z "$QUERY_STRING" ] ; then echo "IF -- EMPTY" ; fi

# Uncomment to get a dump of environment and stardard input
#printf 'Content-Type: text/plain' ; env ; echo ; cat ; echo ; exit

./alspro -q -b ./form_sample.pro ./queryproc.pro -g pro_do_sample
Stripping out all comment lines except the first and other inessential lines leaves:
#!/bin/bash
echo 'Content-Type: text/html'
echo
./alspro -q -b ./form_sample.pro ./queryproc.pro -g pro_do_sample
[4] All the stripped-down lines of form_sample.cgi are needed, but the last one is the live third rail. Using it, the server invokes alspro, with the following effects: Looking into form_sample.pro, we see
pro_do_sample :-
        % Get input from environment
        (getenv('QUERY_STRING', QS) -> true ; QS='DEFAULT QS VALUE HERE'),
        split_comps(QS, QueryStringVals),
        member(seldate=SelDate, QueryStringVals),
        % do something ...
        % finish; return page:
        printf('<H2>SUCCESS!</H2> got date: %t\n', [SelDate]),
        flush_output.
The values of the fields of the html form are returned in the query string (QUERY_STRING) as equations, such as seldate=____. split_comps/2, defined in the file queryproc.pro breaks the query string up into a list of these equations that member/2 can operate on. [4/5] The page P1 to be returned by the cgi transition is the totality of the output written on user_output during execution of pro_do_sample/0. In this case, that is the output of the printf/2 call
        printf('<H2>SUCCESS!</H2> got date: %t\n', [SelDate]),
Note that the final call of pro_do_sample/0 is flush_output to ensure that everything written onto user_output during operation of pro_do_sample/0 has been flushed out to the stream.

The page P1 to which the browser transitions is

SUCCESS!

got date: 2023-05-23

(2) Attaching some Javascript to a button B.

A common Javascript-oriented CGI transition pattern has this high level view:
    Browser displays page P0 with a button B		[1]
	↓
    User presses the button				[2]
	↓ 
    Javascript on button activates CGI interface: 
    	e.g. 'window.location = "DEF.cgi" '		[3]
	↓
    Backend language call(e.g., prolog) returns page P1	[4]
	↓
    Client browser displays HTML page P1		[5]
Below is a simple javascript-oriented sample. You can directly run it by pointing your browser at
	https://kabstuff.com/prolog_web/js_sample/
The sample files can be downloaded from: Javascript-Oriented Sample Files
[1] Now, for javascript, consider the file sample.html, containing an HTML date object and a button:
<HTML>
<HEAD>
<title>sample: js + prolog</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js_sample.js" type="text/javascript"> </script>
</HEAD>
<BODY>
<h1>sample: js + prolog</h1>
Date: <input type="date" id="date_box" value="2023-05-23">
<button type="submit" ONCLICK="submit_date();">Submit Date</button>
</HTML>
[2] The corresponding javascript file js_sample.js is:
function submit_date() {
    const x = document.getElementById("date_box");
    let currentVal = x.value;
	// not necessary; can be eliminated:
    	alert("cv="+currentVal);
    window.location = "js_sample.cgi?foo=bar&seldate="+currentVal;
}
[3] The file 'js_sample.cgi' contains:
#!/bin/bash
#################################################################
#####    js_sample.cgi
#####    NOTE: This file must be executable
#################################################################
#echo 'Content-Type: text/plain'
echo 'Content-Type: text/html'
echo
#For pedagogy, print msg when no query:
if [ -z "$QUERY_STRING" ] ; then echo "IF -- EMPTY" ; fi

# Uncomment to get a dump of environment and stardard input
#printf 'Content-Type: text/plain' ; env ; echo ; cat ; echo ; exit

./alspro -q -b ./pro_sample.pro ./queryproc.pro -g pro_do_sample 
Note that a *.cgi file executes on the command line similarly to a shell script. Sometimes, this can be utilized for debugging. Here, the line "./alspro ..." in the cgi file does the following: So, invoking http://kabstuff.com/prolog_web/js_sample/sample.html, we see page P0:

sample: js + prolog

Date:
Clicking the Submit Date button, we first see the javascript alert
cv=2023-05-23

Closing the javascript alert, file js_sample.cgi will be executed.

Now when steps [1],[2],[3] are carried out, a stream S (back)to the client browser is passed along. When js_sample.cgi is executed, thereby executing

./alspro -q -b ./pro_sample.pro ./queryproc.pro -g pro_do_sample 
the stream S is identified with the standard output stream of the alspro invocation. Everything written and flushed by alspro running pro_do_sample up to the time it exits is accepted by the client browser as the next html page to display (transition to). ( Any output written by pro_do_sample which has not been flushed from the alspro/pro_do_sample image will NOT appear in the transition page displayed by the browser. Consequently, it is advisable to ensure that the last call executed by alspro/pro_do_sample is a call to flush_output/0.)

Note: Development and debuging can utilize the fact that *.cgi files can be executed at the command line just like *.sh files, for example, this will cause the file to execute like a shell file:
sh js_sample.cgi  
This is true for all *.cgi files, including the ones used for the forms-based approach.

Here is the file pro_do_sample.pro:
pro_do_sample :-
	    % Get input from environment
	(getenv('QUERY_STRING', QS) -> true ; QS='DEFAULT QS VALUE HERE'),
        split_comps(QS, QueryStringVals),
	member(seldate=SelDate, QueryStringVals),
	    % do something ...
	    % finish; return page:
	printf('<H2>SUCCESS! got date: %t\n', [SelDate]), 
	flush_output.
The predicate split_comps/2 is defined in the file queryproc.pro.

The page P1 to which the browser transitions is

SUCCESS!

got date: 2023-05-23
In the predicate pro_do_sample/0, the three lines
	(getenv('QUERY_STRING', QS) -> true ; QS='DEFAULT QS VALUE HERE'),
        split_comps(QS, QueryStringVals),
	member(seldate=SelDate, QueryStringVals),
obtain the date value (currentVal) provided by the javascript action:
    window.location = "js_sample.cgi?foo=bar&seldate="+currentVal;
The expression foo=bar& is present in that action only for illustrative purposes, showing how multimple bits of information from the original page can be passed back to prolog executing on the back end.

The page Pseudo Haiku utilizes this machinery together with an interface to an SQLite3 database.