Subject: Re: CGI with SWI-Prolog

From: Paul Singleton <[email-masked]>
Date: Mon, 03 Apr 2000 18:15:01 +0100

Lukas Faulstich wrote:

> Lionel Ains writes:

>  > ...
>  > Is there a non-blocking way to detect the when nothing is
>  > sent to the user input (script called without parameter)?
>  > Are there available librairies to handle the URL
>  > encoding/decoding?

> it is easier to use Java Servlets
> <http://jserv.javasoft.com/index.html>
> to let them do this job. This has the
> advantage that you can maintain a stateful prolog process that handles
> multiple http requests.

This has other potential advantages, e.g. that someone else does
quite a bit of the work for you, takes responsibility for fixing
bugs, and handles lots of nitty gritty details of HTTP requests
and responses that you may need to handle if/when your application
matures, e.g. sessions, cookies, authentication...

If you want to play with servlets, I recommend donwloading Tomcat 3.0
from www.apache.org: this an all-Java servlet host which also acts as
a rudimentary Web server (i.e. you don't need Apache as well).

> While there is the jpl library for calling
> prolog from within java
> <http://blackcat.cat.syr.edu/~fadushin/software/jpl/>, I found it easier
> to use standard input/output for communication.

OK but I've got it to work with JPL, and you're welcome to reuse my
code (I'll email it to anyone who asks).

[potential disadvantage of the JPL approach: the Java VM shares
memory with the JPL library, the Prolog VM and any foreign code
loaded by it, and is thus vulnerable to corruption; i.e. commercial
or corporate Web servers may reasonably refuse to host servlets
which load Java "native methods"]

Basically, a servlet's "doGet" method is called when a GET request
arrives;
it is passed a "request" object and a "response" object; the method body
(which you write) extracts whatever info it needs from the request
object,
stashes its output (HTML, cookies etc.) into the response object, and
returns.

To couple this generically to Prolog I've tried to convert the request
object to a Prolog term, pass it to a Prolog "doGet" goal which should
succeed at most once, returning a response term which I convert (or
interpret) into a response object.

               public void doGet(                    do_get(
  HTTP GET -->     HttpServletRequest request,  -->      +Request,
                   HttpServletResponse response -->      -Response
               )                                     ) :- 

For now at least, the request term contains just about every detail
of the request object (I don't think it costs much to construct this,
and it's simpler than calling back into Java to get the details on
demand) as a "list-of-pairs" map (some of whose values are similar
maps):

Request = 
  [ secure-false,
    method-'GET',
    context_path-'/examples',
    query_string-'a0=proc&a1=pcm13&a2=pcm_2000&a3=0',
    request_uri-'/examples/servlet/WebGoal',
    servlet_path-'/servlet/WebGoal',
    protocol-'HTTP/1.1',
    remote_addr-'10.1.1.36',
    remote_host-'radford.smartarts.co.uk',
    scheme-http,
    server_name-radford,
    server_port-8080,
    headers-[
      'User-Agent'-'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT;
JungeLink)',
      'Accept'- */*,
      'Host'-'radford:8080',
      'Accept-Encoding'-'gzip, deflate',
      'Accept-Language'-'en-gb',
      'Referer'-'http://radford/index.html', 
      'Connection'-'Keep-Alive'
      ],
    parameters-[
      a2-pcm_2000,
      a1-pcm13,
      a0-proc,
      a3-'0'
      ],
    locales-[
      locale(en,'GB','')
      ]
    ]

and you can pull stuff out of this with e.g. memberchk/2

NB the Servlet API enumerates parameters in no particular order

NB some of these atom values could be parsed into terms, but I'd
rather do this in Prolog than in Java

NB this request term could be written to a pipe or socket in Lukas'
idiom, i.e. it's not peculiar to the JPL approach...

NB there are still some details of a request which are not
readily passable by value as above, but I haven't worried about
them (I lack motivation, being nowhere near needing them yet :-)

Paul Singleton