gcl-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gcl-devel] Re: Simple web server in GCL


From: Camm Maguire
Subject: [Gcl-devel] Re: Simple web server in GCL
Date: 17 Jun 2005 09:39:23 -0400
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Greetings, and please excuse my delayed reply!

1) I can certainly make araneida work on GCL if we need it, but I'm
   missing the rationale, and of course time is always tight.  Isn't a
   full blown webserver overkill?  Do we need any functionality not in
   the simple little code we've been playing with?  I thought we were
   at the point to write html producing functions to feed through this
   mechanism. 

2) I think this 

> > )lisp (progn
> >           ; we need a new output stream backed by a string
> >         (setq tmpout (make-string-output-stream))
> >           ; we hold on to the regular algebra output stream
> >         (setq save |$algebraOutputStream|)
> >           ; we capture the regular output into our string stream
> >         (setq |$algebraOutputStream| tmpout)
> >           ; we generate output
> >         (|parseAndInterpret| "(x+1)^9")
> >           ; we get the results from the algebra output stream
> >         (setq result (get-output-stream-string |$algebraOutputStream|))
> >           ; we restore the regular algebra output stream
> >         (setq |$algebraOutputStream| save)
> >           ; and return the result
> >         result)
> > 

   can be simplified to

   )lisp (with-output-to-string (s) (let ((|$algebraOutputStream| s)) 
(|parseAndInterpret| "(x+1)^9")))


Or even

(defun axiom-string-eval (c) 
  (with-output-to-string (s)
     (let ((|$algebraOutputStream| s))
        (|parseAndInterpret| c))))

)lisp (axiom-string-eval "(x+1)^9")

But since you'd be calling this from the server running in lisp, you
don't need the )lisp escape, no?

I take it |$algebraOutputStream| is a declared special.

Take care,

"Page, Bill" <address@hidden> writes:

> Kai,
> 
> On Wednesday, June 15, 2005 12:51 PM you wrote:
> 
> > ...
> > Bill Page wrote:
> >> ...
> >> Right now I know that on the newest version of GCL
> >> (Version_2_6_7pre) it is possible to run a simple
> >> web server in the same image that runs Axiom on both
> >> Linux and Windows.
> >
> > I did not know about that. Which web server is that?
> 
> It consists of just a pair few lines of lisp code written by
> Camm. See emails attached below. Also some related some of my
> notes about web browser page design and details on capturing
> Axiom output from Tim.
> 
> > I do not think that establishing a socket connection is a great
> > deal on Windows. I have never done it myself admittedly, but
> > other Lisp projects do it and it seems to be simple. Besides we
> > have to listen to a socket anyway with Araneida. If there is
> > trouble to get sockets working on Windows we are screwed anyway.
> 
> I am attaching the email thread between between Camm and me
> from the axiom-developer email list  about the "simple web
> server" lisp code that works in both Windows and Linux. It might
> be a bit "thin" to follow, but I think you should probably be able
> to find the relevant parts. Just ask if not. If/when you do
> get access to a running GCL, you should give this a try.
> 
> Regards,
> Bill Page.
> 
> ------------------
> 
> -----Original Message-----
> From: Camm Maguire [mailto:address@hidden
> Sent: Thursday, April 28, 2005 2:52 PM
> To: Bill Page (E-mail)
> Cc: address@hidden; address@hidden
> Subject: Re: [Gcl-devel] Simple web server code for GCL for Windows
> 
> 
> Greetings!  Here's a quick way to get started:
> 
> ============================================================================
> =
> 
> Starting program: /fix/t1/camm/debian/gcl/gcl-2.6.6/unixport/saved_gcl .
> GCL (GNU Common Lisp)  2.6.6 CLtL1    Apr 28 2005 17:10:11
> Source License: LGPL(gcl,gmp), GPL(unexec,bfd)
> Binary License:  GPL due to GPL'ed components: (READLINE BFD UNEXEC)
> Modifications of this banner must retain notice of a compatible license
> Dedicated to the memory of W. Schelter
> 
> Use (help) to get some basic information on how to use GCL.
> 
> >(defun foo (s) 
>   (let* ((get (read s nil 'eof)) 
>        (fn (and (eq get 'get) (string-downcase (read s nil 'eof))))
>        (fn (when (probe-file fn) fn)))
>     (format s "HTTP/1.1 ~S~%~%" (if fn 404 500))
>     (when fn
>       (if (pathname-name (pathname fn))
>         (with-open-file (q fn) (si::copy-stream q s))
>       (dolist (l (directory fn)) (format s "~a~%" (namestring l)))))
>     (close s)))
> 
> >(defun bar (p fn) 
>   (let ((s (si::socket p :server fn))) 
>         (tagbody l 
>                 (when (si::listen s) 
>                         (let ((w (si::accept s))) 
>                                 (foo w))) 
>                 (sleep 3) 
>                 (go l))))
> 
> >(bar 8080 #'foo)
> ============================================================================
> =
> 
> Then point your browser to localhost:8080.  You should be able to get
> directory listings and files.  There is obviously no protocol nor
> error implementation here, but that should be straightforward for the
> web gurus.
> 
> This will accept multiple simultaneous connections and process them
> one at a time.  The delay mechanism can obviously be adjusted.  Each
> connection is stateless -- a multiplexing solution for persistent
> connections can be implemented in like manner.  Also, all connections
> are in the same process.  It is trivial to fork() in linux for each
> connection, but don't know how this would be done on Windows.
> Speaking of which, does MS have select?  There are other hooks for
> allowing work in the image while connections are handled in the
> background, e.g. SIGIO, but don't know the portable nor most desirable
> way of doing this.
> 
> Anything can be done here that one wishes -- my question is, what is
> the advantage vis a vis an external server like apache?  Presumably,
> axiom could spit out results directly instead of being called in a
> cgi, which is of some value.  Anyway, more discussion on where and why
> this should go if anywhere would be great!
> 
> Take care,
> 
> 
> "Page, Bill" <address@hidden> writes:
> 
> > GCL Gurus,
> > 
> > Does anyone know of a simple web server program in lisp that
> > works (or should work) under GCL on both linux and Windows?
> > I am correct to assume that with socket support working properly
> > this should be quite easy (say 20 or 30 lines of code)?
> > 
> > If an example code exists that works on linux, I would like to
> > try it under Windows. If there are problems I would be glad to
> > help try debugging it.
> > 
> > Regards,
> > Bill Page.
> > 
> 
> 
> -----Original Message-----
> From: Camm Maguire [mailto:address@hidden
> Sent: Wednesday, May 04, 2005 1:41 PM
> To: Bill Page (E-mail)
> Cc: 'Mike Thomas'; address@hidden; Paul F. Dietz
> Subject: Re: [Axiom-developer] RE: [Gcl-devel] Re: axiom porting
> 
> Here is a little modification to the server example:
> 
> (defun foo (s) 
>   (let* ((get (read s nil 'eof)) 
>          (fn (and (eq get 'get) (string-downcase (read s nil 'eof))))
>        (dn (if (eql (aref fn (1- (length fn))) #\/) fn
> (si::string-concatenate fn "/")))
>        (dir (directory dn))
>          (file (unless dir (when (probe-file fn) fn))))
>     (format s "HTTP/1.1 ~S~%" (if fn 404 500))
>     (format s "Content-type: text/html~%~%")
>     (format t "get ~a fn ~a dn ~a~%" get fn dn)
>     (cond (file (with-open-file (q file) (si::copy-stream q s)))
>         (dir  (dolist (l dir)
>                 (let ((n (namestring l)))
>                   (format s "<a href=\"~a\">~a</a> <a href=\"~a/\"> /...
> </a><br>~%" n n n)))))
>     (close s)))
> 
> ============================================================================
> =
> 
> These are just toys of course, just meant to illustrate my limited
> understanding of how one can distinguish files from directories in
> *standard* lisp.  We can add anything non-standard we might need, of
> course. 
> 
> 
> -----Original Message-----
> From: Page, Bill [mailto:address@hidden
> Sent: Tuesday, May 03, 2005 4:21 PM
> To: 'Camm Maguire'
> Cc: 'Mike Thomas'; address@hidden; Bill Page (E-mail);
> address@hidden
> Subject: [Gcl-devel] RE: [Axiom-developer] Simple web server code for
> GCLfor Windows
> 
> 
> Camm,
> 
> You are right. The simple GCL web server program that you
> wrote is working on both linux and Windows. Great!
> 
> On Tuesday, May 03, 2005 9:56 AM Camm Maguire wrote:
> 
> >...
> > What this will send to the gcl function 'foo' is 'get /dir'
> > #'foo must find a file or directory by that name to produce
> > output, which I'm guessing does not exist on your system.
> > You can add a diagnostic like: 
> 
> (defun foo (s) 
>   (let* ((get (read s nil 'eof)) 
>          (fn (and (eq get 'get) (string-downcase (read s nil 'eof))))
>          (fn (when (probe-file fn) fn)))
>     (format s "HTTP/1.1 ~S~%" (if fn 404 500))
>     (format s "Content-type: text/html~%~%")
>     (format t "get ~a fn ~a~%" get fn)
>     (when fn
>       (if (pathname-name (pathname fn))
>           (with-open-file (q fn) (si::copy-stream q s))
>         (dolist (l (directory fn)) (format s "~a~%" (namestring l)))))
>     (close s))
> )
> 
> > You can also do 'telnet localhost 8085' and type 'get /dir'
> > to see the output, which I think is likely '404' in my pseudo
> > html error code example. 
> 
> Thanks. This works exactly as you claim. For example on my system
> 
>   http://localhost:8085/msys/1.0/home/bpage/
> 
> produces a list of files and
> 
>   http://localhost:8085/msys/1.0/home/bpage/repository.html
> 
> displays the web page in a browser (See Content-type above).
> 
> Just to play a little (although I know almost knowing about
> lisp :) I also changed the file list to HTML format like this:
> 
>  (format s "<a href=\"~a\">~a</a> <a href=\"~a/\"> /... </a><br>~%"
>    (namestring l) (namestring l) (namestring l)))
> 
> It would be nicer to make the result and the content type depend
> on whether something was a directory or on the type of the file
> etc instead of the syntax of the name, but I could not easily
> discover how to do that in GCL. Specifically how can I tell a
> directory from a file? Can anyone suggest a suitable "Getting
> started in GCL" tutorial?
> 
> Anyway, it seems clear that we could use this approach to develop
> a portable HyperTex browser for Axiom if we decide to go that
> root.
> 
> Regards,
> Bill Page.
> 
> 
> -----Original Message-----
> From: Camm Maguire [mailto:address@hidden
> Sent: Thursday, May 05, 2005 10:19 AM
> To: Bill Page
> Cc: 'Mike Thomas'; address@hidden; Paul F. Dietz
> Subject: Re: [Axiom-developer] RE: [Gcl-devel] Re: axiom porting
> 
> 
> 
> >
> >===========================================================================
> ==
> > >
> > >Here is a little modification to the server example:
> > >
> > > (defun foo (s)  (let* ((get (read s nil 'eof))         (fn (and (eq
> > > get 'get) (string-downcase (read s nil 'eof))))
> > >    (dn (if (eql (aref fn (1- (length fn))) #\/) fn
> (si::string-concatenate fn "/")))
> > >    (dir (directory dn))
> > >         (file (unless dir (when (probe-file fn) fn))))
> 
> This last line should likely read
> 
> (file (or (probe-file fn) dir))
> 
> just to ensure that probe-file takes precedence.
> 
> > >    (format s "HTTP/1.1 ~S~%" (if fn 404 500))
> > >    (format s "Content-type: text/html~%~%")
> > >    (format t "get ~a fn ~a dn ~a~%" get fn dn)
> > >    (cond (file (with-open-file (q file) (si::copy-stream q s)))
> > >     (dir  (dolist (l dir)
> > >             (let ((n (namestring l)))
> > >               (format s "<a href=\"~a\">~a</a> <a href=\"~a/\"> /...
> </a><br>~%" n n n)))))
> > >    (close s)))
> > >
> >
> >===========================================================================
> ==
> > >
> > >These are just toys of course, just meant to illustrate my limited
> > >understanding of how one can distinguish files from directories in
> > >*standard* lisp.  We can add anything non-standard we might need, of
> > > course.
> > I like it. As I said, it works for me with the non-ansi gcl
> Version_2_6_7pre
> > on Windows XP/sp2. No aborts this time.
> > 
> > And I am learning a little lisp too :) Thanks.
> 
> Great!
> 
> Take care,
> 
> 
> -----Original Message-----
> From: Bill Page [mailto:address@hidden
> Sent: Thursday, May 05, 2005 1:44 PM
> To: Camm Maguire
> Cc: Mike Thomas; address@hidden
> Subject: Re: [Axiom-developer] RE: [Gcl-devel] Re: axiom porting
> 
> 
> Camm Maguire wrote:
> 
> >>Using IE, the problem seems to intermittant. It works for a while
> >>with some urls and not others.
> >>    
> >>
> >
> >Does this mean that there are some errors that are 100% reproducible?
> >If so, start with those.
> >  
> >
> Yes.
> 
> >IE appears to be closing the socket before your write completes.  The
> >odd thing is that you report that it is intermittent.  There are two
> >possibiities that come to mind -- either ie insists on a complete set
> >of html headers from the server, or there is a timeout issue.
> >
> Ok, problem solved (I think). It turned out not to be so exotic an issue.
> I modified the web server program as follows:
> 
> -    (format s "HTTP/1.1 ~S~%" (if fn 404 500))
> +    (format s "HTTP/1.1 ~S~%" (if fn 200 404 ))
> 
> If I understand HTTP correctly "404" in the header means "file not found".
> "200" means "ok". "500" means server error. So we were both saying
> "file not found" but then delivering the file anyway. If that's the case
> then it is surprizing that FireFox worked and not surprizing that IE closes
> the socket connection before we can send the file.
> 
> With this change both FireFox and IE now seem to work reliable
> and identically for me.
> 
> Anyway, I will take a closer look at the HTTP standard to make sure
> that our headers are correct and complete.
> 
> Regards,
> Bill Page.
> 
> 
> -----Original Message-----
> From: Camm Maguire [mailto:address@hidden
> Sent: Thursday, May 05, 2005 2:36 PM
> To: Bill Page
> Cc: Mike Thomas; address@hidden
> Subject: Re: [Axiom-developer] RE: [Gcl-devel] Re: axiom porting
> 
> 
> Greetings!
> 
> Bill Page <address@hidden> writes:
> 
> > Camm Maguire wrote:
> > 
> > >>Using IE, the problem seems to intermittant. It works for a while
> > >>with some urls and not others.
> > >>
> > >
> > >Does this mean that there are some errors that are 100% reproducible?
> > >If so, start with those.
> > >
> > Yes.
> > 
> > >IE appears to be closing the socket before your write completes.  The
> > >odd thing is that you report that it is intermittent.  There are two
> > >possibiities that come to mind -- either ie insists on a complete set
> > >of html headers from the server, or there is a timeout issue.
> > >
> > Ok, problem solved (I think). It turned out not to be so exotic an issue.
> > I modified the web server program as follows:
> > 
> > -    (format s "HTTP/1.1 ~S~%" (if fn 404 500))
> > +    (format s "HTTP/1.1 ~S~%" (if fn 200 404 ))
> > 
> 
> Thanks!  This is just what we need -- an html guy!
> 
> BTW, misspoke earlier re: suggested edit to #"foo.  What I meant was:
> 
> (defun foo (s)  
>   (let* ((get (read s nil 'eof))
>          (fn (and (eq get 'get) (string-downcase (read s nil 'eof))))
>        (file (probe-file fn)))
>     
>     (format s "HTTP/1.1 ~S~%" (if fn 200 404))
>     (format s "Content-type: text/html~%~%")
>     
>     (if file 
>       (with-open-file (q file) (si::copy-stream q s))
>       (let ((dir (directory (if (eql (aref fn (1- (length fn))) #\/) fn
> (si::string-concatenate fn "/")))))
>       (dolist (l dir)
>         (let ((n (namestring l)))
>           (format s "<a href=\"~a\">~a</a> <a href=\"~a/\"> /...
> </a><br>~%" n n n)))))
>    (close s)))
> 
> which should function the same as what you have but express the
> precedence better.  This counts on probe-file returning nil for
> directories. 
> 
> Take care,
> 
> > If I understand HTTP correctly "404" in the header means "file not found".
> > "200" means "ok". "500" means server error. So we were both saying
> > "file not found" but then delivering the file anyway. If that's the case
> > then it is surprizing that FireFox worked and not surprizing that IE
> closes
> > the socket connection before we can send the file.
> > 
> > With this change both FireFox and IE now seem to work reliable
> > and identically for me.
> > 
> > Anyway, I will take a closer look at the HTTP standard to make sure
> > that our headers are correct and complete.
> > 
> > Regards,
> > Bill Page.
> > 
> 
> 
> 
> -----Original Message-----
> From: Bill Page [mailto:address@hidden
> Sent: Friday, May 20, 2005 11:20 AM
> To: address@hidden
> Cc: address@hidden
> Subject: [Axiom-developer] Axiom interface via HTTP
> 
> 
> On  May 20, 2005 8:28 AM Tim Daly wrote:
> 
> > Off hand I'm not sure how to do string input but I'm
> > sure it is possible. I'll have to read some code and let
> > you know. Why can't you just feed the string to stdin?
> 
> What I am talking about is using the socket code that Camm
> wrote as an HTTP interface to Axiom. The idea is that the
> input loop of AXIOMsys operates a dedicated special purpose
> web server and the user connects to Axiom using a standard
> browser. There is only one AXIOMsys process running as a
> server that talks directly to the browser. It might be
> invoked by starting AXIOMsys and giving a command like:
> 
>   )set httpmode
> 
> In addition to the HTTP port, as part of the HTTP protocol
> with HTML <form ... method="put"> stdin is involved in
> receiving the contents of the web form. This new "httpmode"
> code in AXIOMsys would parse this input from the web browser,
> format it as an Axiom command and process it as if it was
> normal keyboard input. (This is where I need help to
> understand how to call the Axiom input evaluation from
> within lisp and return the result of the calculation back
> to the httpmode list function. Which in turn gets formatted
> as HTTP and sent back to the browser. All of this is done
> entirely within AXIOMsys without any auxillary processes.
> 
> One simple web page layout that might work would have two
> parts like this:
> 
>   -------------------------------------------------------
>   | Axiom commands ...                                  |
>   |  ______________________________________________     |
>   | | ) -> integrate(sin x, x)                     |^|  |
>   | | ) -> D(%, x)                                 | |  |
>   | |______________________________________________|v|  |
>   |                                        [execute]    |
>   |=====================================================|
>   | Axiom output ...                                    |
>   |                                                     |
>   |  (1)  -cos(x)                                       |
>   |                Type: Union(Expression Integer ... ) |
>   |                                                     |
>   |  (2)  sin (x)                                       |
>   |                            Type: Expression Integer |
>   |                                                     |
>   -------------------------------------------------------
> 
> The first part is an HTML form with a text input field and
> a button labelled [Execute]. The second part contains the
> output generated by AXIOIMsys.
> 
> More complicated page layouts are possible but limitations
> in the way HTTP/HTML works does constrain the design to
> essentially "simplex" (one-way at a time) kind of
> interactions.
> 
> > Check out FAQ 19 to figure out how to get the output in
> > a single line.
> 
> Thanks but I am not sure if this is relevant.
> 
> > Oh, yeah, and remember to use AXIOMsys rather than axiom
> > as the command.
> 
> Yes. Graphics is another issue. I would like to be able
> to have Axiom graphics generate VRML (OpenInventor) output
> for display in the browser.
> 
> Regards,
> Bill Page.
> 
> 
> -----Original Message-----
> From: Bill Page [mailto:address@hidden
> Sent: Friday, May 20, 2005 10:39 PM
> To: address@hidden
> Cc: address@hidden
> Subject: [Axiom-developer] RE: lisp talk
> 
> 
> On May 20, 2005 6:14 PM Tim Daly wrote:
> 
> > There is an embedded command server within AXIOMsys.
> > Look at:
> >
> http://daly.axiom-developer.org/TimothyDaly_files/lisptalk/pages/lisp35.html
> >
> 
> Thanks, Tim. I believe that 
> 
>   parseAndInterpret stringBuf
> 
> is what I was looking for.
> 
> Now, this is boot language code, right? So in lisp I have
> to tack on the | | onto the function name and then I can
> call it like this:
> 
>   (1) -> )lisp (|parseAndInterpret| "integrate(sin x,x)")
> 
>    (1)  - cos(x)
>                           Type: Union(Expression Integer,...)
> 
>   Value = ((|Union| (|Expression| (|Integer|)) (|List| (|Expression|
> (|Integer|)))
>   ) WRAPPED 0 (1 #<vector 10ccde54> (1 0 . -1)) 0 . 1)
> 
>   (2) ->
> 
> and sure enough! Axiom parses and interprets the string.
> Great.
> 
> I presume that there is no reason why this would not work
> when called directly from a lisp function, right? In my
> scheme this string would be passed to Axiom by the http
> webserver code.
> 
> But the result appears as stdout and the value returned
> seems to contain the type information. (What is this WRAPPED
> stuff?)
> 
> > Also, there is some way to do input because the axiom browser
> > already feeds expressions to AXIOMsys thru a socket. 
> 
> Yes, input seems to be no problem.
> 
> > The string output function mentioned in FAQ 19 is a linear
> > form of the output. However Axiom's native output machinery
> > is called CHARYBDIS which was a research project from the
> > 60s with the goal of printing mathematics on typewriters.
> > Axiom still uses that code.
> 
> What I really would like is to see the result also returned
> in the value. I would like to see the output in the form
> of say, a list of strings. So the returned value in the
> example above would be something like this
> 
>   Value = (("- cos(x)" "Type: Union(Expression Integer,...)")
>    ((|Union| (|Expression| (|Integer|)) (|List| (|Expression|
> (|Integer|)))
>    ) WRAPPED 0 (1 #<vector 10ccde54> (1 0 . -1)) 0 . 1)
>   )
> 
> In other words I guess I need the ouput of CHARYBDIS in the
> form of a list of strings instead of in the output stream
> (and later the LaTeX output and the openmath output). Can
> you think of anywhere in Axiom where something like this is
> already done?
> 
> Regards,
> Bill Page.
> 
> 
> -----Original Message-----
> From: Camm Maguire [mailto:address@hidden
> Sent: Monday, May 23, 2005 2:35 PM
> To: address@hidden
> Cc: address@hidden; address@hidden
> Subject: [Gcl-devel] Re: capturing output strings
> 
> 
> Greetings!
> 
> This is an ANSI issue -- traditionally, GCL has used element-type
> 'string-char for strings, but this type was dropped by the ansi
> committee.  We'll clear it up soon hopefully, but for now you can just
> replace 'base-char with 'string-char and it will work.
> 
> Take care,
> 
> address@hidden writes:
> 
> > this seems to fail:
> > 
> > axiom
> > 
> > -> )lisp (setq result (make-array '(0) :element-type 'base-char
> :fill-pointer 0 :adjustable t))
> > 
> > Value = #<vector 0894bde4>
> > 
> > -> )lisp (with-output-to-string (|$algebraOutputStream| result)
> (|parseAndInterpret| "(x+1)^9"))
> > 
> >   >> System error:
> >   #<vector 0894bde4> is not a string with a fill-pointer
> > 
> > This appears to be a bug as result certainly has a fill pointer.
> > 
> > 
> > This is an attempt to capture the output sent to the 
> > stream |$algebraOutputStream| in some more elegant form 
> > (instead of this kludge):
> > 
> > )lisp (progn
> >           ; we need a new output stream backed by a string
> >         (setq tmpout (make-string-output-stream))
> >           ; we hold on to the regular algebra output stream
> >         (setq save |$algebraOutputStream|)
> >           ; we capture the regular output into our string stream
> >         (setq |$algebraOutputStream| tmpout)
> >           ; we generate output
> >         (|parseAndInterpret| "(x+1)^9")
> >           ; we get the results from the algebra output stream
> >         (setq result (get-output-stream-string |$algebraOutputStream|))
> >           ; we restore the regular algebra output stream
> >         (setq |$algebraOutputStream| save)
> >           ; and return the result
> >         result)
> > 
> > t
> > 
> 
> 
> 

-- 
Camm Maguire                                            address@hidden
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah




reply via email to

[Prev in Thread] Current Thread [Next in Thread]