guile-user
[Top][All Lists]
Advanced

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

Re: Web development


From: Alejandro Forero Cuervo
Subject: Re: Web development
Date: Mon, 12 Nov 2001 19:26:05 -0500
User-agent: Mutt/1.2.5i

Hey.

    No, I was unaware of it until this message.  Can you add some
    information as to how guile interfaces with it?

Well, before answering your questions, let me fill you in on the
details of HB.

The idea with HB is separating the interface --the actual HTML-- from
the code.

This is currently achieved with HB modules.  For instance, in a .hb
file you do something like:

    :out main
    <+counter
        src="/home/azul/data/counters"
        id="access"
        inc="1"
        show="yes">
    :

The <+counter> tag is bound to a function (implemented in C in one
module) that...  well, you can guess what it does.

There are two main ways to add new bindings of tags to "objects" (such
as the <+counter> above).

The first way is to declare them in your .hb files with a `:set'
directive.

For instance, when you do (in a .hb file)

    # main gets executed once for every request

    :out main
    <html><body><+hello><+tail></body></html>
    :

    # hello is executed above in <+hello>

    :set (guile.exec) hello
    (display "hello world")
    :

    # this is just a normal object

    :set tail
    <p>Copyright (C) Foo Bar 2001</p>
    :

you declare an object <+hello> that is bound to some code for Guile.
In the rest of your file (such as in the definition of the `main'
object) you forget about how <+hello> was implemented (it could have
been Perl code, for instance) and just call it.  You could pass
parameters to it and check for their values from the Scheme code.

As I said in my previous email to the list, you don't have to use HB's
language, you could just do

    :out (guile.exec) main
    (display "<html><body>")
    (display "hello world")
    (display "</body></html>")
    :

and forget about the first and last lines.

There is another way to add objects such as "<+hello>", "<+tail>" and
"<+counter>", which is defining them in the HB modules.  Each HB
modules has the following methods:

- load: called when the module is load initially.  It tipically opens
  connections to databases or loads data to memory.

- clean: called periodically by HB so modules can free caches and
  resources that haven't got any use in long amounts of time (I
  typically use this to free things from memory that I have in disk).

- init: used by the module to pass information about itself to HB.
  For instance, in this method the module registers the tags it wants
  to bind to its internal functions.  This might sound similar to the
  load method, but it (init) might get called more than once.  For
  instance, this method registers the fact that the "<+counter>" tag
  is meant to be bound to one of its internal functions.

- unload: called when the module is to be discarded.  Can not signal
  an error.

Unfortunately, at this moment it is not possible to create modules in
Scheme, only in C.  However, making it possible to create them in
Guile should not be very hard.  Once this is done, you could have a
.scm file with a function for each of the above methods (clean, load
and unload are optional)...

Now lets get to your questions.

    can we preload guile modules to be called from in the pages?  Can
    we load code that runs once per server instance, rather than once
    per request?

Not at this moment.  At this moment all you can do is bind certain
objects to Guile code.  Objects can have both the form of <+counter>
or <+hello> in the examples above (to be included in HTML) or they can
be public objects (as the `main' object in the examples above, which
gets executed once for every request (this isn't exactly correct, but
it'll do for now)).

Once it becomes possible to create modules in Scheme, the answer will,
obviously, be yes.

    Can we set our own headers and otherwise interface to the hb
    server process?

This should be possible in the current release.  If it's not, it
should be trivial to write.

I'm not sure there are wrappers around most of the C functions, but if
not, they should be very easy to write to do things such as:

- add headers to the HTTP response
- set cookies
- redirect the request
- throw an exception that (unless caught) cancels the request
- adds some information to HB's log
- gets information from the query string/uploaded files
- gets the IP address the request came from
- executes other objects defined in the HB files
- extracts arguments passed to the object (as in <+obj arg="..">)

Very easy above means writing a function callable from Scheme wrapping
the C functions that do these things.

I just checked the relevant file
    <http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/hbuilder/hb/src/hbguile.c>
and it seems that currently we only have wrappers to one of the
C functions for the functionality I listed above, the one that
extracts arguments passed to the object.  For instance, you could do
something like:

    :out main
    <html><body>
    <+show-me width="90%" cellpadding="5" border="2">
    </body></html>
    :

    :set (guile.exec) show-me
    (map display (list
      "<table width='"
      (hb-argument hbargs "width")
      "' cellpadding='"
      (hb-argument hbargs "cellpadding")
      "' border='"
      (hb-argument hbargs "border")
      "'><tr><td>Alejandro Forero</td>"
      "<td>address@hidden</td></tr></table>"))
    :

Hmm, we need to get all those wrappers written.

By the way, most of the functionality in HB can be left out of your
builds (gets #define'd out) passing appropriate parameters to the
configure script... you could disable everything from your build
except the Guile-specific functionality.

    I'd suggesting running squid in front of its httpd instead of
    apache, unless you need other apache features.

This is an interesting suggestion.  :)

Thanks.

Alejo.
http://bachue.com/alejo

--
The mere formulation of a problem is far more essential than its solution.
      -- Albert Einstein.

$0='!/sfldbi!yjoV0msfQ!sfiupob!utvK'x44;print map{("\e[7m \e[0m",chr ord
(chop$0)-1)[$_].("\n")[++$i%77]}split//,unpack'B*',pack'H*',($F='F'x19).
"F0F3E0607879CC1E0F0F339F3FF399C666733333CCF87F99E6133999999E67CFFCCF3".
"219CC1CCC033E7E660198CCE4E66798303873CCE60F3387$F"#Don't you love Perl?

Attachment: pgpNPQE_lVV0C.pgp
Description: PGP signature


reply via email to

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