Subject: Re: mod_lisp over CGI
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 10 Nov 2007 21:52:17 -0600
Newsgroups: comp.lang.lisp
Message-ID: <Bp-dncIEm9bs4avanZ2dnUVZ_ournZ2d@speakeasy.net>
Maciej Katafiasz  <mathrick@gmail.com> wrote:
+---------------
| ... http://mathrick.org/blog/archives/2007/11/10/cgi-lisp/
| Besides variable names translation (which I agree is silly and 
| gratitious), there was a genuine bug in mod_lisp response handling. You 
| were copying the output verbatim, whereas in order to comply with CGI 
| response format, headers ought to be changed from Header\nvalue to 
| Header: value.
+---------------

Ahh... I see the light. You were looking for an *EXACT* replacement
for "mod_lisp", whereas that was never a design requirement or even
a desire of mine for "cgi_sock.c". Rather, my app server code had
initially started out *as* a classic CGI app[1], and "cgi_sock.c" was
just a trivial way to transition it from the model of "run a new Lisp
process every time you get a web hit" to "run a single persistent
Lisp process at boot time and only run a *tiny* CGI program when
you get a web hit".

Given that, you can then understand why "cgi_sock.c" "copies the
output verbatim", because the Lisp side -- originally written *as*
as CGI program -- was already emitting the proper "Header: Value"
format. In fact, it was initially sendin* classical CGI environment
variable format ("NAME=value") request headers across the socket
as well, and doing the splitting on the Lisp side. [That is, using
the C code that's now under the "#if SOCK_PROTOCOL == PROTOCOL_GETENV"
tests.] Only later did I add the "PROTOCOL_MODLISP" flavor and switch
from splitting the CGI vars in the Lisp app to splitting them in
"cgi_sock", since that slightly lessens the amount of per-request
garbage generated on the Lisp side. But I dodn't mess with the
response direction, since that was already fine was it was.

I noticed that you're now using the "PROTOCOL_MODLISP" conditional to
also control the response format, which IMHO is probably a mistake
in the long run. What we should probably both do is keep the request
and response formats orthogonal, and switch to using conditional names
that make that clear, e.g., rename PROTOCOL_GETENV to PROTOCOL_CGI, and
split SOCK_PROTOCOL into SOCK_REQUEST_PROTOCOL and SOCK_RESPONSE_PROTOCOL.
That way, you can use:

    #define SOCK_REQUEST_PROTOCOL PROTOCOL_MODLISP
    #define SOCK_RESPONSE_PROTOCOL PROTOCOL_MODLISP

while I continue to use my preferred hybrid:

    #define SOCK_REQUEST_PROTOCOL PROTOCOL_MODLISP
    #define SOCK_RESPONSE_PROTOCOL PROTOCOL_CGI

and anyone who wants to split the environment strings on the Lisp side
could use:

    #define SOCK_REQUEST_PROTOCOL PROTOCOL_CGI
    #define SOCK_RESPONSE_PROTOCOL PROTOCOL_CGI

+---------------
| > p.s. As long as we're listing problematic(?) features of "cgi_sock.c",
| > note that it doesn't support "keep-alive" connections...
| 
| Can you even implement keep-alive in a CGI handler?
+---------------

You're right, you can't, which is partly why I didn't bother to try .  ;-}

One more thing... In your blog you wrote:

    I dont think it will be very useful without handling POST anyway.

What do you mean by "without handling POST"? *All* of my web apps use
POST very heavily, and "cgi_sock" handles it just fine. [For example,
see <http://rpw3.org/hacks/lisp/appsrv-demo.lhp> which uses POST.]

Did you actually try it? From looking at the "mod_lisp.c" code, I don't
see any obvious reason that it *shouldn't* work. Marc did roughly the
same thing that I did, namely, right after sending the "end\n", check
to see if there's a "request entity" ["mod_lisp.c" calls Apache's
"ap_should_client_block()" whereas "cgi_lisp.c" looks to see if the
environment variable "REQUEST_METHOD" is "POST"], and if so, copy from
the web client to the socket. It really, really *ought* to work the same.


-Rob

[1] Note that by using a Lisp image with all of the CGI stuff
    pre-compiled/loaded, on a modern O.S. with decent file caching
    (such as FreeBSD or Linux) the execution of a whole new Lisp
    image for each CGI call costs well under 50 ms (>20 req/s,
    for trivial requests), which is fast enough for a really
    low-volume site. Still, with almost exactly the same Lisp
    code, the average trivial request through "cgi_sock" takes
    only ~6 ms (~165 req/s) [measureed woth "ab -n100"]. Plus,
    it's actually a lot easier to debug a persistent daemon than
    a "real" CGI app.

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607