unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* CGI scripting with Guile
@ 2008-03-15 22:10 Sebastian Tennant
  2008-03-15 22:40 ` Thien-Thi Nguyen
  2008-03-15 22:48 ` Sebastian Tennant
  0 siblings, 2 replies; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-15 22:10 UTC (permalink / raw)
  To: guile-user

Hi list,

This CGI script:

 #!/usr/bin/guile -s
 !#
 (display "Content-Type: text/plain

 hello world")


works.


But this CGI script:

 #!/usr/bin/guile -s
 !#
 (use-modules (www cgi))
 (display "Content-Type: text/plain

 hello world")


doesn't.

Why doesn't the second script work?  The additional line works in a
guile process running on the server.

Sebastian





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:10 CGI scripting with Guile Sebastian Tennant
@ 2008-03-15 22:40 ` Thien-Thi Nguyen
  2008-03-16  0:41   ` Sebastian Tennant
                     ` (2 more replies)
  2008-03-15 22:48 ` Sebastian Tennant
  1 sibling, 3 replies; 15+ messages in thread
From: Thien-Thi Nguyen @ 2008-03-15 22:40 UTC (permalink / raw)
  To: guile-user

() Sebastian Tennant <sebyte@smolny.plus.com>
() Sun, 16 Mar 2008 00:10:11 +0200

    #!/usr/bin/guile -s
    !#
   works.

    #!/usr/bin/guile -s
    !#
    (use-modules (www cgi))
   doesn't.

   Why doesn't the second script work?

What does the client see for the second case?  I think both cases
are malformed; IIRC, HTTP header lines need to end in CRLF, not just
LF.  The empty line between header and body should likewise be CRLF.
Also, you need to call `cgi:init'.  Appended is examples/id.cgi.in
(you will need to do the @VAR@ substitutions manually and remove the
`load-from-path' calls) from the Guile-WWW 2.21 distribution, for
example.

   The additional line works in a
   guile process running on the server.

Maybe the server is lucky; some systems are (sometimes) slackful.

thi

____________________________________________________________________
#!/bin/sh
exec @GUILE@ -s $0 "$@" # -*- scheme -*-
!#
;;; id.cgi --- the "hello world" of CGI scripts

;;	Copyright (C) 2005 Free Software Foundation, Inc.
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this software; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA  02110-1301  USA

;;; Commentary:

;; This CGI script displays the environment
;; discernable by module (www cgi).

;;; Code:

;; Load the module.  Normally, these explicit loads can be omitted --
;; we use it to help the perpetually confused Guile module system DTRT.

(load-from-path "@abs_top_builddir@/url-coding.scm")
(load-from-path "@abs_top_builddir@/cgi.scm")
(use-modules (www cgi))

;; Abstractions: formatted string output, sectioned output, collection.

(define (fso s . args)
  (apply simple-format #t s args))

(define-macro (section title . body)
  `(begin
     (fso "\nSECTION: ~A\n" ,title)
     ,@body
     (newline)))

(define (collect look save)
  (let loop ((acc '()) (names (cgi:names)))
    (if (null? names)
        (reverse! acc)                  ; rv
        (loop (cond ((look (car names))
                     => (lambda (x) (cons (save (car names) x) acc)))
                    (else acc))
              (cdr names)))))

;; Initialize the context.  For fastcgi environments, this should be
;; called each time to reinitialize the context, and the rest of the
;; file converted from multiple top-level forms into a thunk.

(cgi:init)

;; Output the headers.  Each header is followed by a CRLF pair, and the
;; headers are separated from the body by another CRLF.  In this case,
;; we have only one header.

(fso "Content-Type: text/plain\r\n\r\n")

;; Output the body.

(fso "=== Output from ~S (@PACKAGE_NAME@ @PACKAGE_VERSION@) ===\n"
     (command-line))

(section
 "Environment Variables (using `cgi:getenv')"
 (for-each (lambda (var)
             (fso "\n~A:\n~S\n" var (cgi:getenv var)))
           '(server-hostname
             gateway-interface
             server-port
             request-method
             path-info
             path-translated
             script-name
             query-string
             remote-host
             remote-addr
             authentication-type
             remote-user
             remote-ident
             content-type
             content-length
             http-user-agent
             http-cookie
             server-software-type
             server-software-version
             server-protocol-name
             server-protocol-version
             http-accept-types)))

(section
 "Form Data (using `cgi:form-data?', `cgi:names' and `cgi:values')"
 (if (cgi:form-data?)
     (let ((ls (cgi:names)))
       (fso "(~A names)\n" (length ls))
       (for-each (lambda (name)
                   (fso "\n~A:\n~S\n" name (cgi:values name)))
                 ls))
     (fso "(none)\n")))

(section
 "File Uploads (using `cgi:uploads')"
 (let* ((ls (append! (collect cgi:uploads (lambda (name u) u))))
        (tot (length ls)))
   (cond ((= 0 tot)
          (fso "(none)\n"))
         (else
          (fso "(~A uploads)\n" tot)
          (for-each (lambda (u)
                      (let* ((minfo (object-property u #:guile-www-cgi))
                             (m (lambda (part) (assq-ref minfo part))))
                        (fso "\n~A: ~A (~A, ~A bytes)\n~A\n"
                             (m #:name)
                             (m #:filename)
                             (m #:mime-type)
                             (string-length u)
                             (m #:raw-mime-headers))))
                    ls)))))

(section
 "Cookies (using `cgi:cookies')"
 (let* ((ls (collect cgi:cookies cons))
        (tot (apply + (map length (map cdr ls)))))
   (cond ((= 0 tot)
          (fso "(none)\n"))
         (else
          (fso "(~A cookies)\n" tot)
          (for-each (lambda (name/c)
                      (fso "\n~A: ~A\n" (car name/c) (length (cdr name/c)))
                      (for-each (lambda (c)
                                  (fso " ~A\n" c))
                                (cdr name/c)))
                    ls)))))

;;; id.cgi ends here





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:10 CGI scripting with Guile Sebastian Tennant
  2008-03-15 22:40 ` Thien-Thi Nguyen
@ 2008-03-15 22:48 ` Sebastian Tennant
  2008-03-15 22:52   ` Sebastian Tennant
  1 sibling, 1 reply; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-15 22:48 UTC (permalink / raw)
  To: guile-user

Quoth Sebastian Tennant <sebyte@smolny.plus.com>:
> The additional line works in a guile process running on the server.

I should have said

  a guile REPL(?) shell like thing

not just

  a guile process

S





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:48 ` Sebastian Tennant
@ 2008-03-15 22:52   ` Sebastian Tennant
  0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-15 22:52 UTC (permalink / raw)
  To: guile-user

Quoth Sebastian Tennant <sebyte@smolny.plus.com>:
> Quoth Sebastian Tennant <sebyte@smolny.plus.com>:
>> The additional line works in a guile process running on the server.
>
> I should have said
>
>   a guile REPL(?) shell like thing
>
> not just
>
>   a guile process
>
This post was not a reply to _your_ last post.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:40 ` Thien-Thi Nguyen
@ 2008-03-16  0:41   ` Sebastian Tennant
  2008-03-16  9:16     ` Thien-Thi Nguyen
  2008-03-16 12:51   ` Sebastian Tennant
  2008-03-16 12:56   ` Sebastian Tennant
  2 siblings, 1 reply; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-16  0:41 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> What does the client see for the second case?

I will use a Guile http request and hopefully then I'll be able to give
you an intelligent answer.

> I think both cases are malformed; IIRC, HTTP header lines need to end
> in CRLF, not just LF.

How is that achieved (in scheme (lisp) forms)?

> [...]
> Also, you need to call `cgi:init'.  

cgi:init is a little... dark... in terms of documentation.

  (procedure-source cgi:init)

isn't much help... (yet).

> Appended is examples/id.cgi.in (you will need to do the @VAR@
> substitutions manually and remove the `load-from-path' calls) from the
> Guile-WWW 2.21 distribution, for example.

I have 2.21... it will be a while before I take this all in.

>    The additional line works in a
>    guile process running on the server.
>
> Maybe the server is lucky; some systems are (sometimes) slackful.

Maybe the machines live on in the end.

S





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16  0:41   ` Sebastian Tennant
@ 2008-03-16  9:16     ` Thien-Thi Nguyen
  2008-03-16 10:41       ` Sebastian Tennant
  0 siblings, 1 reply; 15+ messages in thread
From: Thien-Thi Nguyen @ 2008-03-16  9:16 UTC (permalink / raw)
  To: guile-user

() Sebastian Tennant <sebyte@smolny.plus.com>
() Sun, 16 Mar 2008 02:41:39 +0200

   How is [CRLF] achieved (in scheme (lisp) forms)?

You can use the characters #\cr and #\newline, or the string "\r\n".
In id.cgi.in, for example, we use the string variant.

   cgi:init is a little... dark... in terms of documentation.

Thanks for pointing this out.  I have increased the `cgi:init'
documentation (slightly) to be:

| (Re-)initialize internal data structures.  This must be called before
| calling any other @samp{cgi:foo} procedure.  For FastCGI, call this
| ``inside the loop'' (that is, for each CGI invocation).

This will appear in 2.22.  If you use Git and would like to monitor
pre-release hacking, see <http://www.gnuvola.org/wip/> (guile-www).

     (procedure-source cgi:init)

   isn't much help... (yet).

Probably `procedure-source' is a poor way to learn how `cgi:init'
works; better to look at cgi.scm directly.

thi





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16  9:16     ` Thien-Thi Nguyen
@ 2008-03-16 10:41       ` Sebastian Tennant
  0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-16 10:41 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
>    How is [CRLF] achieved (in scheme (lisp) forms)?
>
> You can use the characters #\cr and #\newline, or the string "\r\n".

I can do that  :-)

> Probably `procedure-source' is a poor way to learn how `cgi:init'
> works; better to look at cgi.scm directly.

Indeed.

Many thanks ttn.






^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:40 ` Thien-Thi Nguyen
  2008-03-16  0:41   ` Sebastian Tennant
@ 2008-03-16 12:51   ` Sebastian Tennant
  2008-03-16 13:06     ` Thien-Thi Nguyen
  2008-03-16 12:56   ` Sebastian Tennant
  2 siblings, 1 reply; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-16 12:51 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> What does the client see for the second case?

 #!/usr/bin/guile -s
 !#
 (use-modules (www cgi)) ;LOAD
 (cgi:init)              ;INIT
 (simple-format
         #t
         "Content-Type: text/plain\r\n\r\n~A"
         "hello world")

---/---

 guile> (www:get "http://www.../hw.scm")
 ""
 guile> (www:http-head-get "http://www.../hw.scm")
 #("HTTP/1.0" "200" "OK" ((server . "lighttpd/1.4.18") (date . "Sun, 16
  Mar 2008 12:43:32 GMT") (content-length . "0") (connection . "close"))
  "")

---/---

It 'works' without LOAD and INIT.

Seb





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-15 22:40 ` Thien-Thi Nguyen
  2008-03-16  0:41   ` Sebastian Tennant
  2008-03-16 12:51   ` Sebastian Tennant
@ 2008-03-16 12:56   ` Sebastian Tennant
  2008-03-16 13:16     ` Thien-Thi Nguyen
  2 siblings, 1 reply; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-16 12:56 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> Appended is examples/id.cgi.in

This is incredibly useful.  Thank you for pointing it out.

Just out of curiostiy, why the '.in' file extension?  Is it to do with
make?

> #!/bin/sh
> exec @GUILE@ -s $0 "$@" # -*- scheme -*-
> !#

Also, why the shell?

Seb





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16 12:51   ` Sebastian Tennant
@ 2008-03-16 13:06     ` Thien-Thi Nguyen
  2008-03-16 15:11       ` Sebastian Tennant
  0 siblings, 1 reply; 15+ messages in thread
From: Thien-Thi Nguyen @ 2008-03-16 13:06 UTC (permalink / raw)
  To: guile-user

() Sebastian Tennant <sebyte@smolny.plus.com>
() Sun, 16 Mar 2008 14:51:19 +0200

    guile> (www:get "http://www.../hw.scm")
    ""
    guile> (www:http-head-get "http://www.../hw.scm")
    #("HTTP/1.0" "200" "OK" ((server . "lighttpd/1.4.18") (date . "Sun, 16
     Mar 2008 12:43:32 GMT") (content-length . "0") (connection . "close"))
     "")

   It 'works' without LOAD and INIT.

Perhaps the module (www cgi) is not being loaded.
What happens when you insert the form:
 (simple-format (open-output-file "/tmp/alive") "ALIVE! ~S\n" cgi:init)
between LOAD and INIT?  (What are the contents of file /tmp/alive after?)

thi





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16 12:56   ` Sebastian Tennant
@ 2008-03-16 13:16     ` Thien-Thi Nguyen
  2008-03-18 20:19       ` Sebastian Tennant
  0 siblings, 1 reply; 15+ messages in thread
From: Thien-Thi Nguyen @ 2008-03-16 13:16 UTC (permalink / raw)
  To: guile-user

() Sebastian Tennant <sebyte@smolny.plus.com>
() Sun, 16 Mar 2008 14:56:20 +0200

   This is incredibly useful.  Thank you for pointing it out.

You're welcome.  If you find any bugs in it, i'm all ears...

   Just out of curiostiy, why the '.in' file extension?
   Is it to do with make?

It's customary for autoconf-substituted files (see configure.in)
to use the .in extension.  Running the configure script produces
id.cgi from id.cgi.in, with the @var@ sequences expanded.

   > #!/bin/sh
   > exec @GUILE@ -s $0 "$@" # -*- scheme -*-
   > !#

   Also, why the shell?

This preamble can accomodate Guile installed in different places.
For example, in my case, @GUILE@ becomes /home/ttn/local/bin/guile,
but for you it would most likely be different.  You should be able
to safely replace it w/ the preamble used in your test script.

thi





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16 13:06     ` Thien-Thi Nguyen
@ 2008-03-16 15:11       ` Sebastian Tennant
  0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-16 15:11 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> () Sebastian Tennant <sebyte@smolny.plus.com>
> () Sun, 16 Mar 2008 14:51:19 +0200
>
>     guile> (www:get "http://www.../hw.scm")
>     ""
>     guile> (www:http-head-get "http://www.../hw.scm")
>     #("HTTP/1.0" "200" "OK" ((server . "lighttpd/1.4.18") (date . "Sun, 16
>      Mar 2008 12:43:32 GMT") (content-length . "0") (connection . "close"))
>      "")
>
>    It 'works' without LOAD and INIT.
>
> Perhaps the module (www cgi) is not being loaded.

Exaclty right.

> What happens when you insert the form:
>  (simple-format (open-output-file "/tmp/alive") "ALIVE! ~S\n" cgi:init)

Not necessary.  It occurred to me to chack lighty's error log:

  ERROR: no code for module (www cgi)

I've fixed the problem using the meta switch:

#!/usr/bin/guile \
-L /usr/local/share/guile/site -s
!#

That's one cool switch :-)






^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-16 13:16     ` Thien-Thi Nguyen
@ 2008-03-18 20:19       ` Sebastian Tennant
  2008-03-19  7:22         ` Thien-Thi Nguyen
  0 siblings, 1 reply; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-18 20:19 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> () Sebastian Tennant <sebyte@smolny.plus.com>
> () Sun, 16 Mar 2008 14:56:20 +0200
>
>    This is incredibly useful.  Thank you for pointing it out.
>
> You're welcome.  If you find any bugs in it, i'm all ears...

I'll do my best... :-)

>    Just out of curiostiy, why the '.in' file extension?
>    Is it to do with make?
>
> It's customary for autoconf-substituted files (see configure.in)
> to use the .in extension.  Running the configure script produces
> id.cgi from id.cgi.in, with the @var@ sequences expanded.

Noted.  Thanks for the explanation.

>    > #!/bin/sh
>    > exec @GUILE@ -s $0 "$@" # -*- scheme -*-
>    > !#
>
>    Also, why the shell?
>
> This preamble can accomodate Guile installed in different places.
> For example, in my case, @GUILE@ becomes /home/ttn/local/bin/guile,
> but for you it would most likely be different.  You should be able
> to safely replace it w/ the preamble used in your test script.

Hmm, OK.  Again, just out of interest, why doesn't a simple

  #!@GUILE@ -s
  !#

suffice?

Thanks again thi.

Sebastian






^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-18 20:19       ` Sebastian Tennant
@ 2008-03-19  7:22         ` Thien-Thi Nguyen
  2008-03-19  9:24           ` Sebastian Tennant
  0 siblings, 1 reply; 15+ messages in thread
From: Thien-Thi Nguyen @ 2008-03-19  7:22 UTC (permalink / raw)
  To: guile-user

() Sebastian Tennant <sebyte@smolny.plus.com>
() Tue, 18 Mar 2008 22:19:27 +0200

   Hmm, OK.  Again, just out of interest, why doesn't a simple

     #!@GUILE@ -s
     !#

   suffice?

It probably would, in this case.  For a (semi-)exhaustive
treatment of script headers, see:
http://www.gnuvola.org/software/guile/doc/guile_002dtools-edit_002dscript_002dheader.html

thi





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: CGI scripting with Guile
  2008-03-19  7:22         ` Thien-Thi Nguyen
@ 2008-03-19  9:24           ` Sebastian Tennant
  0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Tennant @ 2008-03-19  9:24 UTC (permalink / raw)
  To: guile-user

Quoth Thien-Thi Nguyen <ttn@gnuvola.org>:
> () Sebastian Tennant <sebyte@smolny.plus.com>
>    Hmm, OK.  Again, just out of interest, why doesn't a simple
>
>      #!@GUILE@ -s
>      !#
>
>    suffice?
>
> It probably would, in this case.  For a (semi-)exhaustive
> treatment of script headers, see:
> http://www.gnuvola.org/software/guile/doc/guile_002dtools-edit_002dscript_002dheader.html

Interesting reading.  Thanks for the pointer.

Sebastian





^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2008-03-19  9:24 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-15 22:10 CGI scripting with Guile Sebastian Tennant
2008-03-15 22:40 ` Thien-Thi Nguyen
2008-03-16  0:41   ` Sebastian Tennant
2008-03-16  9:16     ` Thien-Thi Nguyen
2008-03-16 10:41       ` Sebastian Tennant
2008-03-16 12:51   ` Sebastian Tennant
2008-03-16 13:06     ` Thien-Thi Nguyen
2008-03-16 15:11       ` Sebastian Tennant
2008-03-16 12:56   ` Sebastian Tennant
2008-03-16 13:16     ` Thien-Thi Nguyen
2008-03-18 20:19       ` Sebastian Tennant
2008-03-19  7:22         ` Thien-Thi Nguyen
2008-03-19  9:24           ` Sebastian Tennant
2008-03-15 22:48 ` Sebastian Tennant
2008-03-15 22:52   ` Sebastian Tennant

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).