source: project/wiki/eggref/5/awful @ 37629

Last change on this file since 37629 was 37629, checked in by wasamasa, 7 weeks ago

Fix links

File size: 123.8 KB
Line 
1== Awful
2
3[[toc:]]
4
5=== Description
6
7awful provides an application and an extension to ease the development of web-based applications.
8
9Here's a short summary of awful features:
10
11* Straightforward interface to databases (currently supported are [[http://www.postgresql.org/|PostgreSQL]] and [[http://www.sqlite.org/|SQLite3]])
12* Support for page dispatching via regular expressions
13* Easy access to query string and body request variables from HTTP requests
14* Ajax support via [[http://jquery.com/|jQuery]]
15* Reasonably flexible (several configuration parameters)
16* Compiled pages made easy
17* Session inspector
18* Web REPL
19* SXML support
20
21==== Screencasts
22
23Here are some screencasts about awful:
24
25; [[https://parenteses.org/mario/awful/awful.ogv|Awful in 35s]] : a 35 seconds video showing the installation of the awful egg and the development of a "hello, world" example
26
27; [[https://parenteses.org/mario/awful/awful-guess.ogv|Number guessing game]] : a video demonstrating the development of a very simple number guessing game using ajax and the web REPL
28
29=== Mailing list
30
31To subscribe to the awful mailing list, just send a message to
32awful@librelist.com.  Your first message will only serve for
33subscription purposes and will not hit the actual mailing list.  You
34then will receive a confirmation message you should reply to.
35
36After you confirm your subscription, send messages to
37awful@librelist.com.
38
39The mailing list archives are available at
40[[http://librelist.com/browser/awful/|http://librelist.com/browser/awful/]].
41
42=== Author
43
44[[/users/mario-domenech-goulart|Mario Domenech Goulart]]
45
46
47
48=== Repository
49
50The git repository for the awful source code is hosted by GitHub:
51[[https://github.com/mario-goulart/awful|https://github.com/mario-goulart/awful]].
52
53Additionally, there are some extra repositories related to awful (they
54are not required to use awful):
55
56* [[https://github.com/mario-goulart/awful-init-scripts|awful-init-scripts]]: init scripts for some operating systems
57* [[https://github.com/mario-goulart/awful-doc|awful-doc]]: the source code for this document
58* [[https://github.com/mario-goulart/awful-codemirror|awful-codemirror]]: the JavaScript files used by the web REPL
59
60
61
62=== Requirements
63
64The following eggs are required:
65
66* [[/egg/spiffy|spiffy]]
67* [[/egg/spiffy-cookies|spiffy-cookies]]
68* [[/egg/spiffy-request-vars|spiffy-request-vars]]
69* [[/egg/json|json]]
70* [[/egg/http-session|http-session]]
71* [[/egg/sxml-transforms|sxml-transforms]]
72* [[/eggref/5/srfi-1|srfi-1]] (CHICKEN 5 only -- in CHICKEN 4 it is a core unit)
73* [[/eggref/5/srfi-13|srfi-13]] (CHICKEN 5 only -- in CHICKEN 4 it is a core unit)
74* [[/eggref/5/srfi-69|srfi-69]] (CHICKEN 5 only -- in CHICKEN 4 it is a core unit)
75
76
77=== Components
78
79awful is composed by two parts: an application, which can be thought
80as a web server; and an extension, which provides most of the
81supported features.
82
83=== A "Hello, world!" example
84
85Here's a "Hello, world!" example to be run by awful ({{hello-world.scm}}).
86
87<enscript highlight=scheme>
88(cond-expand
89  (chicken-4
90    (use awful))
91  (chicken-5
92    (import awful)))
93
94(define-page (main-page-path)
95  (lambda ()
96    "Hello, world!"))
97</enscript>
98
99To run this example, execute (assuming {{awful}} is installed and its
100location is in your system's {{PATH}}):
101
102  $ awful hello-world.scm
103
104Then access http://localhost:8080 using your favorite web browser.
105
106Without any configuration, awful listens on port 8080.  Since awful
107uses Spiffy behind the scenes, you can configure the web server
108parameters using Spiffy's.
109
110{{define-page}} is the primitive procedure to define pages.  In the
111simplest case, it takes as arguments a path to the page and a
112procedure to generate the page contents. The path to the page you use
113as the first argument is the same to be used as the path part of the
114URL you use to access the page.
115
116In the example we use the {{main-page-path}} parameter, which is one
117of the awful configuration parameters.  The default is {{"/"}}.
118
119If you look at the page source code, you'll see that awful created an
120HTML page for you.  Awful uses the [[/egg/html-utils|html-utils]]'s
121{{html-page}} procedure behind the scenes.  You can customize the page
122either by passing {{html-page}}'s keyword parameters to
123{{define-page}} or by creating you own page definer based on
124{{define-page}} (see more information on how to do that in the Tips &
125Tricks section).
126
127You can also use some global page-related parameters if all pages use
128the same CSS, doctype and charset ({{page-css}}, {{page-doctype}} and
129{{page-charset}}, respectively).
130
131
132An alternative way to write Awful '''scripts''' is by using the
133{{#!/path/to/awful}} shebang line.  Example:
134
135<enscript highlight=scheme>
136#! /usr/bin/awful
137
138(cond-expand
139  (chicken-4
140    (use awful))
141  (chicken-5
142    (import awful)))
143
144(define-page (main-page-path)
145  (lambda ()
146    "Hello, world!"))
147</enscript>
148
149Then you just need to run your script (assuming the file has execution
150permissions):
151
152  $ ./hello-world.scm
153
154
155=== Accessing request variables
156
157Awful provides a procedure ({{$}}) to access variables from the
158request, both from the query string (GET method) and from the request
159body (e.g., POST method).
160
161Here's a modified "Hello, world!" example to greet some person instead
162of the whole world:
163
164<enscript highlight=scheme>
165(cond-expand
166  (chicken-4
167    (use awful))
168  (chicken-5
169    (import awful)))
170
171(define-page (main-page-path)
172  (lambda ()
173    `("Hello, " ,($ 'person "world") "!")))
174</enscript>
175
176So, restart the web server to reload the code, then access the main
177page using an argument, represented by the {{person}} query string
178variable: {{http://localhost:8080/?person=Mario}}. You'll see a page
179showing {{Hello, Mario!}}.
180
181
182=== Re-evaluating the code by reloading the page
183
184When we upgraded our "Hello, world!" example to the improved one which
185can use an argument passed through the URL, we needed to modify the
186code and restart the web server to reload the application code.  Awful
187provides a way to reload the code via URL without restarting the
188server.  To do that, we can define a special page whose handler just
189reloads the code:
190
191<enscript highlight=scheme>
192(cond-expand
193  (chicken-4
194    (use awful))
195  (chicken-5
196    (import awful)))
197
198(define-page "/reload"
199  (lambda ()
200    (reload-apps (awful-apps))
201    "Reloaded"))
202</enscript>
203
204and restart the awful server.  Now, whenever you want to reload the
205application code, access {{http://localhost:8080/reload}}.
206
207You can control which IP addresses can access the reload page by using
208the {{page-access-control}} parameter.  For example, allowing only the
209localhost to reload the apps:
210
211<enscript highlight=scheme>
212(cond-expand
213  (chicken-4
214    (use awful spiffy))
215  (chicken-5
216    (import awful spiffy)))
217
218(page-access-control
219 (lambda (path)
220   (if (equal? path "/reload")
221       (member (remote-address) '("127.0.0.1"))
222       #t)))
223</enscript>
224
225When used in development mode (see the {{--development-mode}} command
226line option for the awful application server), awful automatically
227defines a {{/reload}} path (available to any host) for reloading all
228the applications.
229
230
231=== Using ajax
232
233Awful provides a way to (hopefully) make the use of ajax
234straightforward for web applications.
235
236By default, the ajax support is disabled, but it can be easily
237globally enabled by setting the {{enable-ajax}} parameter to {{#t}}.
238When you enable ajax via {{enable-ajax}}, all the pages defined via
239{{define-page}} will be linked to the jQuery JavaScript library. If
240you want just a couple of pages to have ajax support (i.e., not global
241ajax support), you can use the {{use-ajax}} keyword parameter for
242{{define-page}}, so only the pages defined with {{use-ajax: #t}} have
243ajax support.
244
245When you have ajax enabled and you want to disable it for specific
246pages, you can pass {{#t}} as the value for the {{define-page}}
247keyword parameter {{no-ajax}}.
248
249The URL of the jQuery file can be customized by setting the
250{{ajax-library}} parameter (the default is Google's API jQuery file).
251
252So, if we now change our code to
253
254<enscript highlight=scheme>
255(cond-expand
256  (chicken-4
257    (use awful))
258  (chicken-5
259    (import awful)))
260
261(define-page (main-page-path)
262  (lambda ()
263    `("Hello, " ,($ 'person "world") "!"))
264  use-ajax: #t)
265</enscript>
266
267and reload the application, we'll have our page linked to jQuery.
268
269Awful provides some procedures to do ajax.  We start by the more
270generic one ({{ajax}}) to reply the page greetings when we click
271"Hello, <person>!".
272
273<enscript highlight=scheme>
274(cond-expand
275  (chicken-4
276    (use awful))
277  (chicken-5
278    (import awful)))
279
280(define-page (main-page-path)
281  (lambda ()
282    (ajax "greetings" 'greetings 'click
283          (lambda ()
284            '(b "Hello, awful!"))
285          target: "greetings-reply")
286    `((a (@ (href "#") (id "greetings"))
287         "Hello, " ,($ 'person "world") "!")
288      (div (@ (id "greetings-reply")))))
289  use-ajax: #t)
290</enscript>
291
292The {{ajax}} procedure uses at least four arguments:
293
2941. The URL path to the server-side handler (a string).  This path is relative to {{ajax-namespace}} parameter (default is {{ajax}}.  So, in the example, we'll have {{/ajax/greetings}} as the ajax path to be generated if we pass {{ajax}} as the first argument.
295
2962. The ID of the DOM element to observe.
297
2983. The event to be handled
299
3004. The procedure to be run on the server-side.
301
302So, in the example, {{ajax}} will bind the fourth argument (the
303procedure) to the first argument (the path) on the server side. Then
304it will add JavaScript code to the page in order to wait for click
305events for the element of ID {{greetings}}.  When we click "Hello,
306<person>!", we'll get {{Hello, awful!}} printed on the page as reply.
307{{ajax}} updates the DOM element whose id is the value of the
308{{target}} keyword parameter ({{"greetings-reply"}}, in the example).
309
310For the very specific case of creating links that execute server side
311code when clicked, awful provides the {{ajax-link}} procedure.  So our
312example could be coded like:
313
314<enscript highlight=scheme>
315(cond-expand
316  (chicken-4
317    (use awful))
318  (chicken-5
319    (import awful)))
320
321(define-page (main-page-path)
322  (lambda ()
323    `(,(ajax-link "greetings" 'greetings  "Hello, awful!"
324                  (lambda ()
325                    '(b "Hello, awful!"))
326                  target: "greetings-reply")
327      (div (@ (id "greetings-reply")))))
328  use-ajax: #t)
329</enscript>
330
331
332=== Adding arbitrary JavaScript code to pages
333
334Awful provides a procedure which can be used to add arbitrary
335JavaScript code to the page. It's called {{add-javascript}}.  Here's
336an example using JavaScript's {{alert}} and our "Hello, world!"
337example:
338
339<enscript highlight=scheme>
340(cond-expand
341  (chicken-4
342    (use awful))
343  (chicken-5
344    (import awful)))
345
346(define-page (main-page-path)
347  (lambda ()
348    (add-javascript "alert('Hello!');")
349    `(,(ajax-link "greetings" 'greetings "Hello, awful!"
350                  (lambda ()
351                    '(b "Hello, awful!"))
352                  target: "greetings-reply")
353      (div (@ (id "greetings-reply")))))
354  use-ajax: #t)
355</enscript>
356
357
358
359=== Database access
360
361To access databases, you need some of the awful eggs which provide
362database access.  Currently, these are the possible options:
363
364* [[/egg/awful-postgresql|awful-postgresql]] (for PostgreSQL databases, using the [[/egg/postgresql|postgresql]] egg)
365
366* [[/egg/awful-sqlite3|awful-sqlite3]] (for SQLite3 databases, using the [[/egg/sqlite3|sqlite3]] egg)
367* [[/egg/awful-sql-de-lite|awful-sql-de-lite]] (for SQLite3 databases, using the [[/egg/sql-de-lite|sql-de-lite]] egg)
368
369As with ajax, database access is not enabled by default.  To enable
370it, you need to pick one the awful database support eggs and call the
371{{enable-db}} procedure.  Since version 0.10, and differently from the
372{{enable-*}} parameters, {{enable-db}} is a zero-argument procedure
373provided by each of awful database-support eggs.  So, if you use
374{{awful-postgresql}}, the {{enable-db}} procedure will automatically
375set up awful to use a PostgreSQL database.
376
377Additionally, to access the db, you need to provide the credentials.
378You can provide the credentials by setting the {{db-credentials}}
379parameter.  See the documentation for the eggs corresponding to the
380database type you are using ([[/egg/postgresql|postgresql]] for
381PostgreSQL and [[/egg/sqlite3|sqlite3]] or
382[[/egg/sql-de-lite|sql-de-lite]] for SQLite3.)
383
384To actually query the database, there's the {{$db}} procedure, which
385uses as arguments a string representing the query and, optionally, a
386default value (a keyword parameter) to be used in case the query
387doesn't return any result. {{$db}} returns a list of lists. Below is
388an usage example:
389
390<enscript highlight=scheme>
391(cond-expand
392  (chicken-4
393    (use awful awful-postgresql))
394  (chicken-5
395    (import awful awful-postgresql)))
396
397(enable-db)
398
399(db-credentials '((dbname . "my-db")
400                  (user . "mario")
401                  (password . "secret")
402                  (host . "localhost")))
403
404(define-page "db-example"
405  (lambda ()
406    ($db "select full_name, phone from users")))
407</enscript>
408
409''Hint'': for SQLite3 databases, {{db-credentials}} should be the path
410to the database file.
411
412There's also the {{$db-row-obj}} procedure for when you want to access
413the results of a query by row name.  {{$db-row-obj}} returns a
414procedure of two arguments: the name of the field and, optionally, a
415default value to be used in case the field value is {{#f}}.
416
417<enscript highlight=scheme>
418(define-page "db-example"
419  (lambda ()
420    (let ((& ($db-row-obj "select full_name, phone from users where user_id=1")))
421      `((p "Full name: " ,(& 'full_name))
422        (p "Phone: " ,(& 'phone)))))
423</enscript>
424
425''Warning'': currently {{$db-row-obj}} is only implemented for PostgreSQL.
426
427If you need more flexibility to query the database, you can always use
428the {{(db-connection}}) parameter to get the database connection
429object and use it with the procedures available from the your favorite
430database egg API.
431
432
433=== Login pages and session
434
435Awful provides a very basic (awful?) support for creating
436authentication pages.
437
438The basic things you have to do is:
439
4401. Enable the use of sessions:
441
442<enscript highlight=scheme>
443(enable-session #t)
444</enscript>
445
4462. Set the password validation parameter.  This parameter is a two
447argument procedure (user and password) which returns a value (usually
448{{#t}} or {{#f}}) indicating whether the password is valid for the
449given user.  The default is a procedure which returns {{#f}}.  Let's
450set it to a procedure which returns {{#t}} if the user and the
451password are the same:
452
453<enscript highlight=scheme>
454(valid-password?
455  (lambda (user password)
456    (equal? user password)))
457</enscript>
458
4593. Define a login trampoline, which is an intermediate page accessed when redirecting from the login page to the main page.
460
461<enscript highlight=scheme>
462(define-login-trampoline "/login-trampoline")
463</enscript>
464
4654. Create a login page.  Awful provides a simple user/password login form ({{login-form}}), which we are going to use.  Here's our full example so far (using the basic "Hello, world!" as main page).
466
467<enscript highlight=scheme>
468(cond-expand
469  (chicken-4
470    (use awful))
471  (chicken-5
472    (import awful)))
473
474(enable-session #t)
475
476(define-login-trampoline "/login-trampoline")
477
478(valid-password?
479  (lambda (user password)
480    (equal? user password)))
481
482(define-page (main-page-path)
483  (lambda ()
484    "Hello world!"))
485
486(define-page (login-page-path)
487  (lambda ()
488    (login-form))
489  no-session: #t)
490</enscript>
491
492That's the very basic we need to set an auth page.  If the password is
493valid for the given user, awful will perform a redirect to the main
494page ({{main-page-path}} parameter) passing the {{user}} variable and
495its value in the query string .  If the password is not valid, awful
496will redirect to the login page ({{login-page-path}} parameter) and
497pass the following variables and values:
498
499; {{reason}} : the reason why awful redirected to the login page. It may be {{invalid-password}}, for when the password is invalid for the given user; or {{invalid-session}} for when the session identifier is not valid (e.g., the session expired).
500
501; {{attempted-page}} : the URL path to page the user tried to access, but couldn't because either he/she was not logged in or he/she provided an invalid session identifier.
502
503; {{user}} : the user used for the form user field.
504
505Now we're gonna change our main page to store the user in the session
506and retrieve it to make the greetings message:
507
508<enscript highlight=scheme>
509(define-page (main-page-path)
510  (lambda ()
511    ($session-set! 'user ($ 'user))
512    `("Hello " ,($session 'user "world") "!"))
513</enscript>
514
515Here we can see the two procedures to access the session: {{$session}}
516and {{$session-set!}}.
517
518{{$session-set!}} accepts two arguments: the first one is the name of
519the session variable and the second one is its value.
520
521{{$session}} takes the name of the session variable as argument and
522returns its session value.  We can optionally use a second argument to
523specify a default value, in case the session variable is not bound or
524is {{#f}}.
525
526
527=== Session inspector
528
529Awful provides a session inspector, so we can easily see the session
530contents for a given session identifier.  By default, the session
531inspector is disabled.  We can enabled it using the
532{{enable-session-inspector}} procedure, passing the session inspector
533URL path as argument:
534
535<enscript highlight=scheme>
536(enable-session-inspector "session-inspector")
537</enscript>
538
539Now, if you log in and try to access
540{{http://localhost:8080/session-inspector}}, you'll get ... an access
541denied page.
542
543Awful provides a way to control access to the session inspector
544({{session-inspector-access-control}} parameter).  The
545{{session-inspector-access-control}} parameter is a thunk which
546returns {{#f}} or some other value to indicate whether the access to
547the session inspector is allowed or not. By default, it blocks all
548access.  Let's configure it so we can access the session inspector
549from the local machine (whose IP address is 127.0.0.1):
550
551<enscript highlight=scheme>
552(session-inspector-access-control
553 (lambda ()
554   (member (remote-address) '("127.0.0.1"))))
555</enscript>
556
557Regarding to the access denied message, you can customize it by
558setting the {{session-inspector-access-denied-message}}.
559
560Now we can access {{http://localhost:8080/session-inspector}} and see
561the session contents.
562
563''Note'': if {{enable-session-cookie}} is {{#f}}, you need to pass the
564session identifier in the query string (e.g.,
565{{http://localhost:8080/session-inspector?sid=the-session-id-here}}).
566
567Here's a screenshot:
568
569[[image://parenteses.org/mario/img/awful/session-inspector.png|Awful session inspector]]
570
571When {{enable-session}} is {{#t}} and the {{--development-mode}}
572option is given to the awful application server, the session inspector
573is automatically enabled and is available from {{/session-inspector}}.
574
575=== Web REPL
576
577For further run-time, server-side web hacking, awful provides a REPL
578that you can use via web browser.
579
580The web REPL can use either a plain HTML textarea for the input area
581or a more featureful editor (based on
582[[http://codemirror.net|codemirror]]).  By default, the web REPL uses
583the ''fancy'' editor.
584
585The activation and control access are basically the same as for the
586session inspector.  The relevant procedure and parameters are:
587
588* {{enable-web-repl}}
589* {{web-repl-access-control}}
590* {{web-repl-access-denied-message}}
591* {{enable-web-repl-fancy-editor}}
592* {{web-repl-fancy-editor-base-uri}}
593
594Here's a screenshot (using the fancy editor):
595
596[[image://parenteses.org/mario/img/awful/fancy-web-repl.png|Awful web REPL]]
597
598When the {{--development-mode}} option is given to the awful
599application server, the web REPL is automatically enabled and is
600available from {{/web-repl}}. The awful application server also
601accepts the {{--disable-web-repl-fancy-editor}} command line option to
602disable the web REPL fancy editor.
603
604
605=== Pages access control
606
607To allow/deny access to pages, you can use the {{page-access-control}}
608parameter.  It's a one-argument procedure (the page path) which can
609be set to determine if the access to the page is allowed or not.
610
611The example bellow shows a very silly access control to the main page:
612it only allows the access when the value of the request variable
613{{user}} is {{"mario"}}:
614
615<enscript highlight=scheme>
616(cond-expand
617  (chicken-4
618    (use awful))
619  (chicken-5
620    (import awful)))
621
622(enable-session #t)
623
624(define-login-trampoline "/login-trampoline")
625
626(valid-password?
627 (lambda (user password)
628   (equal? user password)))
629
630(page-access-control
631 (lambda (path)
632   (or (member path `(,(login-page-path) "/login-trampoline")) ;; allow access to login-related pages
633       (and (equal? ($ 'user) "mario")
634            (equal? path (main-page-path))))))
635
636(define-page (main-page-path)
637  (lambda ()
638    "Hello world"))
639
640(define-page (login-page-path)
641  (lambda ()
642    (login-form))
643  no-session: #t)
644</enscript>
645
646You can customize the access denied message by setting the
647{{page-access-denied-message}} with a one-argument procedure (the
648page path).
649
650
651=== Compiled pages
652
653Since Chicken is a compiler and our pages are Chicken code, we can
654compile them to have faster pages.  We just need to compile our app
655and pass the generated {{.so}} to the {{awful}} application:
656
657  $ csc -s hello-world.scm
658  $ awful hello-world.so
659
660Notice that Chicken doesn't support reloading {{.so}} files, so, to
661reload your application, you'll have to restart awful.
662
663
664=== Multiple applications support
665
666Parameters are thread-safe, but [[/egg/spiffy|Spiffy]] (the web server
667used by awful) doesn't guarantee that each request will be handled by a
668different thread, so awful has to provide a way to overcome that,
669otherwise hosting multiple applications under the same virtual host
670can be very painful, since it's not guaranteed that parameters will be
671reset at each request (awful does reset some critical and obviously
672per-request ones like {{http-request-variables}},
673{{awful-response-headers}}, {{db-connection}} and {{sid}}).
674
675Awful provides the possibility of running hooks when handling
676requests, so you can set parameters for multiple applications in a way
677that they don't interfere with others.
678
679See the documentation for
680[[/egg/awful#add-request-handler-hook|{{add-request-handler-hook!}}]]
681for an example about how to do that.
682
683=== The awful application server
684
685Awful consists of an application server and an extension module.  The
686awful application server is a command line program whose usage is:
687
688  $ awful --help
689  Usage:
690    awful [ -h | --help ]
691    awful [ -v | --version ]
692    awful [ <options> ] [ <app1> [ <app2> ... ] ]
693 
694  <options>:
695 
696  --development-mode
697    Run awful in development mode.  When in development mode, the
698    web-repl, the session inspector and a special path for reload
699    applications are automatically activated.  They get bound to /web-repl,
700    /session-inspector and /reload, respectively, and access to them is only
701    permited from the local host.  In this mode, error messages and call
702    chains are printed to the client.  Running awful with --development-mode
703    is not recommended for applications in production.
704 
705  --privileged-code=<file1>[,<file2> ...]
706    Files with code to be run with administrator privileges (e.g., setting
707    port < 1024).
708 
709  --disable-web-repl-fancy-editor
710    By default, the web-repl uses the "fancy" editor (Codemirror), with
711    JavaScript to perform code highlight and other useful editor features.
712    This option disables the "fancy" editor -- the web-repl will then
713    provide a simple textarea for editing code.
714 
715  --ip-address=<ip address>
716    Bind the web server to the given IP address.
717 
718  --port=<port number>
719    Make the web server listen to the given port number.
720 
721
722{{<app1> <app2> ...}} are files containing code to be loaded by the
723awful application server.
724
725{{--ip-address}} can be used to bind the web server to the given IP
726address.
727
728{{--port}} can be used to make the web server listen to the given
729port.
730
731{{--ip-address}} and {{--port}} take precedence over the Spiffy
732parameters to specify the server IP address ({{server-bind-address}})
733and port ({{server-port}}).
734
735The {{--development-mode}} option is intended to be used during the
736development of your web application.  It's not recommended to run
737awful with {{--development-mode}} in production.  The development mode
738enables the web REPL and the session inspector (when
739{{enable-session}} is {{#t}}) for the localhost, prints error messages
740and backtraces to the client (e.g., web browser) and HTTP server
741debugging messages to the {{current-error-port}}.  It also makes the
742{{/reload}} path available for reloading awful applications.
743
744When in development mode, the web REPL and the session inspector are
745available from the {{/web-repl}} and {{/session-inspector}} paths.
746
747If you enable the development mode you can still use
748{{enable-web-repl}} and {{enable-session-inspector}} to customize
749their respective paths and access control procedures (although the
750development mode always allows access to web REPL and session
751inspector for the localhost).
752
753The {{--disable-web-repl-fancy-editor}} command line option disables
754the web REPL fancy editor.
755
756The {{--privileged-code}} command line options specify code to be run
757in privileged mode, for the cases when you specify a user/group to run
758the server ({{spiffy-user}}/{{spiffy-group}}).  In this case, you
759usually run awful as a user with administrator privileges (e.g.,
760{{root}} in Unix[-like] systems) and spiffy switches to the specified
761user/group.  To make things clearer, let's take a look at awful's
762workflow:
763
764         |
765         v
766 load privileged code
767         |
768         v
769      listen
770         |
771         v
772  switch user/group
773         |
774         v
775  load applications
776         |
777         v
778       accept
779         |
780         v
781
782As you can see, the privileged code is loaded and evaluated
783'''before''' switching user/group.  So, if you run awful with
784administrator privileges, the privileged code will the loaded with
785administrator privileges.  Running code with administrator privileges
786is usually not recommended, but it is necessary if you want, for
787example, to specify the user and group to switch to before accepting
788connections. So, the {{--privileged-code}} command line option should
789be used strictly to specify code which must be run with administrator
790privileges (like specifying server user/group and
791[[/egg/awful-ssl|enabling SSL]], for example).
792
793The privileged code is '''not''' reloaded when you reload applications
794via a defined reload page.
795
796=== Deploying Awful
797
798Here are some tips about how to deploy awful on your system.
799
800
801==== On Unix[-like] systems
802
803Create a user for running awful.  For example, on GNU/Linux systems,
804you can use the adduser program:
805
806  # adduser --system --no-create-home --disabled-password --disabled-login --group awful
807
808This will create a user and a group called {{awful}}.
809
810
811Create a directory for the awful configuration file:
812
813  # mkdir /etc/awful
814
815
816Create a directory for log files:
817
818  # mkdir /var/log/awful
819
820Create a directory for static files:
821
822  # mkdir /var/www/awful
823
824You may also want to create a directory for your awful applications:
825
826  # mkdir /var/lib/awful
827
828
829Create configuration files for awful.  In the privileged configuration
830file ({{privileged.conf}} below) you can set all the configuration
831parameters for awful and spiffy which require administrator
832privileges.
833
834In another file ({{awful.conf}} below) you can put whatever code which
835does not need administrator privileges.
836
837Here's some example configuration for awful listening on port 80
838(strictly speaking, [[/egg/spiffy|spiffy]] -- the actual web server --
839listens on this port):
840
841===== privileged.conf
842
843<enscript highlight=scheme>
844;; -*- scheme -*-
845(cond-expand
846  (chicken-4
847    (use awful spiffy))
848  (chicken-5
849    (import awful spiffy)))
850
851(spiffy-user "awful")
852(server-port 80)
853(root-path "/var/www/awful")
854(debug-log "/var/log/awful/debug.log")
855(error-log "/var/log/awful/error.log")
856</enscript>
857
858
859===== awful.conf
860<enscript highlight=scheme>
861(load "/var/lib/awful/my-app") ;; if you don't use file suffixes, Chicken will
862                               ;; pick .so files when you compile your apps
863</enscript>
864
865
866Set the permissions for the configuration, log, static files and awful
867applications directories:
868
869  # chown -R awful:awful /etc/awful /var/log/awful /var/www/awful /var/lib/awful
870
871
872Set up an init script for your system.  Basically, it should call
873
874  /usr/bin/awful --privileged-code=/etc/awful/privileged.conf /etc/awful/awful.conf &> /var/log/awful/init.log &
875
876If awful doesn't start, take a look at {{/var/log/awful/init.log}}
877
878You can find an [[https://raw.github.com/mario-goulart/awful-init-scripts/master/debian|init script]] for [[http://www.debian.org|Debian]] systems (or derivatives, like [[http://www.ubuntulinux.com|Ubuntu]]) at the [[https://github.com/mario-goulart/awful-init-scripts|awful-init-scripts repository]].  Here are the steps to install it:
879
880  # cd /etc/init.d
881  # wget https://raw.github.com/mario-goulart/awful-init-scripts/master/debian -O awful
882  # chmod 755 awful
883  # update-rc.d awful defaults
884
885There's also an [[https://raw.github.com/mario-goulart/awful-init-scripts/master/gentoo|init script for Gentoo]] (by [[/users/david-krentzlin|David Krentzlin]]).
886
887=== Awful & SSL
888
889To make awful serve pages using SSL, see the documentation for the [[/egg/awful-ssl|awful-ssl]] egg.
890=== List of user configurable parameters
891
892==== SXML (parameters)
893
894===== {{enable-sxml}}
895<parameter>(enable-sxml [boolean])</parameter>
896
897Deprecated.  Since version 1.0.0, this parameter has no effect.  It is
898going to be removed in future versions.
899
900
901===== {{sxml->html}}
902<parameter>(sxml->html [procedure])</parameter>
903
904The procedure used to transform SXML into HTML. The default value is:
905
906<enscript highlight=scheme>
907(let ((rules `((literal *preorder* . ,(lambda (t b) b))
908               . ,universal-conversion-rules*)))
909  (lambda (sxml)
910    (with-output-to-string
911      (lambda ()
912        (SRV:send-reply (pre-post-order* sxml rules))))))
913</enscript>
914
915This parameter has been introduced in awful 0.36.
916
917==== Debugging (parameters)
918
919===== {{debug-file}}
920<parameter>(debug-file [file path])</parameter>
921
922If {{#f}}, indicates that debugging should be disabled.  When set to a
923string, it should be the path to the file where the debug messages go
924(when {{debug}} or {{debug-pp}} is used.)
925
926The default value is {{#f}}.
927
928
929===== {{debug-db-query?}}
930<parameter>(debug-db-query? [boolean])</parameter>
931
932When not {{#f}}, all queries passed to {{$db}} and to {{$db-row-obj}}
933are printed to the debug file.
934
935The default value is {{#f}}.
936
937
938===== {{debug-db-query-prefix}}
939<parameter>(debug-db-query-prefix [string])</parameter>
940
941Prefix to be used for queries debugging when {{debug-db-query}} is not
942{{#f}}.
943
944The default value is {{""}}.
945
946
947===== {{debug-resources}}
948<parameter>(debug-resources [boolean])</parameter>
949
950When {{#t}}, enables debugging of awful's resources table (an alist
951mapping paths (or regexes) and vhost paths to their corresponding
952procedures to be executed on the server side upon request).  The
953debugging data is sent to the file pointed by {{debug-file}}.  The
954default value is {{#f}}.
955
956
957==== Database (parameters)
958
959===== {{db-credentials}}
960<parameter>(db-credentials [boolean or list])</parameter>
961
962Credentials to be used to access the database (see the documentation
963for the egg corresponding to the database backend you selected.)  When
964{{#f}}, no database access is performed.
965
966The default value is {{#f}}.
967
968
969==== Ajax (parameters)
970
971===== {{ajax-library}}
972<parameter>(ajax-library [string])</parameter>
973
974URL or path to the ajax library (currently only
975[[http://jquery.com|jQuery]] is supported.)
976
977The default value is
978{{"http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"}}
979
980
981===== {{enable-ajax}}
982<parameter>(enable-ajax [boolean])</parameter>
983
984When {{#t}}, makes {{define-page}} link the {{ajax-library}} to the
985generated page.  Its effect is global, that is, once {{enable-ajax}}
986is set to {{#t}}, all pages defined via {{define-page}} will be linked
987to the ajax library, unless when the {{no-ajax}} keyword parameter is
988explicitly set.
989
990The default value is {{#f}}.
991
992
993===== {{ajax-namespace}}
994<parameter>(ajax-namespace [string])</parameter>
995
996Name to be used as a namespace for ajax URL paths.
997
998The default value is {{"ajax"}}.
999
1000
1001===== {{ajax-invalid-session-message}}
1002<parameter>(ajax-invalid-session-message [string])</parameter>
1003
1004The message to be used when attempting the make an ajax call using an
1005invalid session identifier.
1006
1007The default value is {{"Invalid session"}}.
1008
1009
1010
1011==== Sessions (parameters)
1012
1013===== {{enable-session}}
1014<parameter>(enable-session [boolean])</parameter>
1015
1016When {{#t}}, session support is enabled.
1017
1018The default value is {{#f}}.
1019
1020
1021===== {{enable-session-cookie}}
1022<parameter>(enable-session-cookie [boolean])</parameter>
1023
1024When {{#t}}, awful uses cookies to store the session identifier.
1025Otherwise, the session identifier is passed as a value in the query
1026string or in the request body. The default value is {{#t}}.
1027
1028
1029===== {{session-cookie-name}}
1030<parameter>(session-cookie-name [string])</parameter>
1031
1032The name of the cookie for storing the session identifier.  The default
1033value is {{"awful-cookie"}}.
1034
1035
1036===== {{session-cookie-setter}}
1037<parameter>session-cookie-setter</parameter>
1038
1039A one-argument procedure (the sid) that is called when
1040creating/refreshing the session.
1041
1042The default value is the following procedure:
1043
1044<enscript highlight=scheme>
1045(lambda (sid)
1046  (set-cookie! (session-cookie-name) sid))
1047</enscript>
1048
1049
1050==== Access control (parameters)
1051
1052===== {{page-access-control}}
1053<parameter>(page-access-control [procedure])</parameter>
1054
1055A one-argument (URL path of the current page) procedure which tells
1056whether the access to the page is allowed or not.
1057
1058The default value is {{(lambda (path) #t)}}.
1059
1060
1061===== {{page-access-denied-message}}
1062<parameter>(page-access-denied-message [procedure])</parameter>
1063
1064A one-argument (URL path of the current page) procedure which returns
1065the access denied message in SXML.
1066
1067The default value is {{(lambda (path) '(h3 "Access denied."))}}.
1068
1069
1070===== {{valid-password?}}
1071<parameter>(valid-password? [procedure])</parameter>
1072
1073A two-argument (user and password) procedure which indicates whether
1074the given password is valid for the given user.
1075
1076The default value is {{(lambda (user password) #f)}}.
1077
1078
1079==== Pages (parameters)
1080
1081===== {{page-doctype}}
1082<parameter>(page-doctype [string])</parameter>
1083
1084The doctype (see the [[/egg/doctype|doctype]] egg) to be applied to
1085all pages defined by {{define-page}}.  It can be overwritten by
1086{{define-page}}'s {{doctype}} keyword parameter.
1087
1088The default value is {{""}}.
1089
1090
1091===== {{page-css}}
1092<parameter>(page-css [boolean or string])</parameter>
1093
1094The CSS file to be linked by all pages defined by {{define-page}}.  It
1095can be overwritten by {{define-page}}'s {{css}} keyword parameter.
1096See [[/egg/html-utils|html-utils]]'s {{html-page}} procedure to know
1097about the {{css}} keyword parameter syntax.
1098
1099The default value is {{#f}} (no CSS).
1100
1101
1102===== {{page-charset}}
1103<parameter>(page-charset [boolean or string])</parameter>
1104
1105The page charset to be used by all pages defined by {{define-page}}.
1106It can be overwritten by {{define-page}}'s {{charset}} keyword
1107parameter.
1108
1109The default value is {{#f}} (no explicit charset).
1110
1111
1112===== {{page-template}}
1113<parameter>(page-template [procedure])</parameter>
1114
1115A one-mandatory-argument procedure to be used by {{define-page}}
1116(unless {{define-page}}'s {{no-template}} keyword parameter is set to
1117{{#f}}) to generate HTML pages. Although the procedure yielded by this
1118parameter takes only one mandatory argument, the following keyword
1119arguments are passed:
1120
1121* css
1122* title
1123* doctype
1124* headers
1125* charset
1126* literal-style?
1127
1128The default value is {{html-page}} (see the
1129[[/egg/html-utils|html-utils]] egg documentation.)
1130
1131
1132===== {{page-exception-message}}
1133<parameter>(page-exception-message [procedure])</parameter>
1134
1135A one-argument procedure to be used when an exception occurs while
1136{{define-page}} tries to evaluate its contents.
1137
1138The default value is {{(lambda (exn) '(h3 "An error has occurred while processing your request."))}}
1139
1140
1141
1142==== Page paths (parameters)
1143
1144===== {{main-page-path}}
1145<parameter>(main-page-path [string])</parameter>
1146
1147The URL path to the app main page.
1148
1149The default value is {{"/"}}.
1150
1151
1152===== {{app-root-path}}
1153<parameter>(app-root-path [string])</parameter>
1154
1155The base path to be used by the application.  All the pages defined by
1156{{define-page}} will use {{app-root-path}} as the base directory.  For
1157example, if {{app-root-path}} is set to {{"/my-app"}} and
1158{{"my-page"}} is used as first argument to {{define-page}}, the page
1159would be available at {{http://<server>:<port>/my-app/my-page}}.
1160
1161The default value is {{"/"}}.
1162
1163'''Important''': this parameter is evaluated both at page definition
1164time and page request handling time.
1165
1166
1167===== {{login-page-path}}
1168<parameter>(login-page-path [string])</parameter>
1169
1170The URL path for the login page.  When creating a login page, be sure
1171to set the {{no-session}} keyword parameter for {{define-page}} to
1172{{#t}}, otherwise you'll get an endless loop.
1173
1174The default value is {{"/login"}}.
1175
1176
1177
1178==== Headers (parameters)
1179
1180===== {{awful-response-headers}}
1181<parameter>(awful-response-headers [alist])</parameter>
1182
1183An alist to specify the headers to be used in the response.  If the
1184{{content-length}} header is not provided, awful will calculate it
1185automatically.
1186
1187Here's an example:
1188
1189<enscript highlight=scheme>
1190(use awful)
1191
1192(enable-sxml #t)
1193
1194(define (define-json path body)
1195  (define-page path
1196    (lambda ()
1197      (awful-response-headers '((content-type "text/json")))
1198      (body))
1199    no-template: #t))
1200
1201
1202(define-json (main-page-path)
1203  (lambda ()
1204    '("{a: 1}")))
1205</enscript>
1206
1207
1208
1209==== Web REPL (parameters)
1210
1211===== {{web-repl-access-control}}
1212<parameter>(web-repl-access-control [procedure])</parameter>
1213
1214A no-argument procedure to control access to the web REPL.
1215
1216The default value is {{(lambda () #f)}}.
1217
1218
1219===== {{web-repl-access-denied-message}}
1220<parameter>(web-repl-access-denied-message [SXML])</parameter>
1221
1222Message to be printed when the access to the web REPL is denied.
1223
1224The default value is {{'(h3 "Access denied.")}}.
1225
1226
1227===== {{enable-web-repl-fancy-editor}}
1228<parameter>(enable-web-repl-fancy-editor [boolean])</parameter>
1229
1230Indicates whether the web REPL should use a fancier editor for the
1231input area.  The editor is based on
1232[[http://codemirror.net|codemirror]].  Without the fancy editor, the
1233input area is a simple HTML textarea.  The default value for
1234{{use-fancy-editor}} is {{#t}}.
1235
1236
1237===== {{web-repl-fancy-editor-base-uri}}
1238<parameter>(web-repl-fancy-editor-base-uri [string])</parameter>
1239
1240The URI which indicates the fancy editor source files (JavaScript and
1241CSS) location.  The default value is
1242{{http://parenteses.org/awful/codemirror}}.
1243
1244
1245
1246==== Session inspector (parameters)
1247
1248===== {{session-inspector-access-control}}
1249<parameter>(session-inspector-access-control [procedure])</parameter>
1250
1251A no-argument procedure to control access to the session inspector.
1252
1253The default value is {{(lambda () #f)}}.
1254
1255
1256===== {{session-inspector-access-denied-message}}
1257<parameter>(session-inspector-access-denied-message [SXML])</parameter>
1258
1259Message to be printed when the access to the session inspector is denied.
1260
1261The default value is {{'(h3 "Access denied.")}}.
1262
1263
1264==== JavaScript (parameters)
1265
1266===== {{enable-javascript-compression}}
1267<parameter>(enable-javascript-compression [boolean])</parameter>
1268
1269Enable JavaScript compression support.  When enabled the compressor
1270set by {{javascript-compressor}} is used.
1271
1272The default value is {{#f}}.
1273
1274
1275===== {{javascript-compressor}}
1276<parameter>(javascript-compressor [procedure])</parameter>
1277
1278A one-argument procedure which receives JavaScript code and returns
1279it compressed.  Only used when {{enable-javascript-compression}} is
1280not {{#f}}.
1281
1282The default value is the {{identity}} procedure.
1283
1284A possible value for {{javascript-compressor}} is {{jsmin-string}}
1285(see the [[/egg/jsmin|jsmin]] egg.)
1286
1287
1288===== {{javascript-position}}
1289<parameter>(javascript-position [symbol])</parameter>
1290
1291A symbol indicating the position of JavaScript code in the generated
1292pages.  Possible values are {{top}} (in the page headers) and
1293{{bottom}} (right before {{</body>}}).  The default value is {{top}}.
1294
1295
1296===== {{literal-script/style?}}
1297<parameter>(literal-script/style? [boolean])</parameter>
1298
1299When {{#f}} (the default value), convert special HTML characters in
1300JavaScript and in CSS code to their corresponding HTML entities.  When
1301non-{{#f}}, leave the special HTML characters untouched.
1302
1303This parameter was introduced in version 0.39.
1304
1305
1306=== List of read-only parameters available to users
1307
1308Note: these parameters should not be explicitly set and when their use
1309is needed, it's a string sign you're doing something you shouldn't
1310(except for {{db-connection}}, which can be used by procedures from
1311the [[/egg/postgresql|postgresql]] egg API).
1312
1313
1314===== {{http-request-variables}}
1315<parameter>(http-request-variables)</parameter>
1316
1317The per-request value returned by
1318[[/egg/spiffy-request-vars|spiffy-request-vars]]'s {{request-vars}}.
1319
1320
1321===== {{db-connection}}
1322<parameter>(db-connection)</parameter>
1323
1324A per-request database connection object.  The connection is
1325automatically opened and closed by awful in a per-request basis
1326(unless databases are not being used or the {{no-db}} keyword
1327parameter for {{define-page}} is {{#t}}.)
1328
1329
1330===== {{page-javascript}}
1331<parameter>(page-javascript)</parameter>
1332
1333JavaScript code to be added to the pages defined by {{define-page}}.
1334
1335
1336===== {{sid}}
1337<parameter>(sid)</parameter>
1338
1339The session identifier.
1340
1341
1342===== {{awful-apps}}
1343<parameter>(awful-apps)</parameter>
1344
1345The list of awful applications, as given to the awful server when
1346invoked from the command line.
1347
1348
1349===== {{development-mode?}}
1350<parameter>(development-mode?)</parameter>
1351
1352Indicates whether awful is running in development mode (see the
1353{{--development-mode}} command line option for the awful application
1354server).
1355
1356=== List of procedures and macros
1357
1358
1359==== Miscellaneous
1360
1361===== {{awful-version}}
1362<procedure>(awful-version)</procedure>
1363
1364Return the awful version (a string).
1365
1366===== {{awful-resources-table}}
1367
1368Return the resources table used by awful.  The resources table is
1369represented by a hash table whose format is described below:
1370
1371; keys: lists in the following format: {{(path-matcher vhost-root-path method)}}. {{path-matcher}} is the first argument given to {{define-page}} and can be either a string, a regular expression object or a procedure. {{vhost-root-path}} is the documents root path for the virtual host and is a string.  {{method}}, a symbol, is the HTTP method bound to the resource.
1372
1373; values: procedures representing the page handlers (the second argument given to {{define-page}}).
1374
1375
1376==== JavaScript
1377
1378===== {{include-javascript}}
1379<procedure>(include-javascript . files)</procedure>
1380
1381A shortcut to {{(<script> type: "text/javascript" src: file)}} for
1382each file in {{files}}.
1383
1384
1385===== {{add-javascript}}
1386<procedure>(add-javascript . code)</procedure>
1387
1388Add arbitrary JavaScript code to the pages defined by {{define-page}}
1389and {{define-session-page}}.
1390
1391Note that the {{literal-script/style?}} parameter may affect special
1392characters in JavaScript code.
1393
1394
1395==== CSS
1396===== {{add-css}}
1397<procedure>(add-css . code)</procedure>
1398
1399Add arbitrary CSS code to the pages defined by {{define-page}}
1400and {{define-session-page}}.
1401
1402Note that the {{literal-script/style?}} parameter may affect special
1403characters in CSS code.
1404
1405This procedure was introduced in version 0.39.
1406
1407
1408==== Debugging
1409
1410===== {{debug}}
1411<procedure>(debug . args)</procedure>
1412
1413Print {{args}}, concatenated, to the file {{debug-file}}.
1414
1415
1416===== {{debug-pp}}
1417<procedure>(debug-pp arg)</procedure>
1418
1419Pretty-print {{arg}} to the file {{debug-file}}.
1420
1421
1422
1423==== Sessions and authentication
1424
1425===== {{$session}}
1426<procedure>($session var #!optional default)</procedure>
1427
1428Return the value of {{var}} in the session (or {{default}} if {{var}}
1429does not exist or is {{#f}}).
1430
1431
1432===== {{$session-set!}}
1433<procedure>($session-set! var #!optional val)</procedure>
1434
1435If {{var}} is a quoted symbol, set the value of {{var}} to {{val}}.
1436If {{val}} is not provided, {{var}} will have its value set to {{#f}}.
1437
1438{{var}} can be an alist mapping session variable names to their
1439corresponding values.
1440
1441Examples:
1442
1443<enscript highlight=scheme>
1444($session-set! 'foo "foo value")
1445
1446($session-set! '((foo . "foo value")
1447                 (bar . "bar value")
1448                 (baz . "baz value")))
1449</enscript>
1450
1451
1452===== {{link}}
1453<procedure>(link url text . rest)</procedure>
1454
1455Return a session-aware HTML code for a link, using the {{<a>}}
1456procedure from [[/egg/html-tags|html-tags]].
1457
1458The {{rest}} arguments are the same as the ones for the {{<a>}}
1459procedure from [[/egg/html-tags|html-tags]], plus the following:
1460
1461; {{no-session}} : a boolean.  If {{#t}}, forces {{link}} to ignore the session even when {{enable-session}} is {{#t}}.
1462
1463; {{arguments}} : an alist mapping variable names to their corresponding values, to be passed to uri-common's {{form-urlencode}} procedure.
1464; {{separator}} : the value to the {{separator}} keyword argument to be passed to to uri-common's {{form-urlencode}} procedure.
1465
1466When {{enable-session}} is {{#t}}, {{link}} automatically encodes the session identifier in the URI (unless {{no-session}} is {{#t}}).
1467
1468
1469===== {{form}}
1470<procedure>(form contents . rest)</procedure>
1471
1472Return a session-aware HTML code for a form, using the {{<form>}}
1473procedure from [[/egg/html-tags|html-tags]].
1474
1475The {{rest}} arguments are the same as the ones for the {{<form>}}
1476procedure from [[/egg/html-tags|html-tags]], plus {{no-session}}, a
1477boolean.  If {{no-session}} is {{#t}}, it forces {{form}} to ignore
1478the session even when {{enable-session}} is {{#t}}.
1479
1480When {{enable-session}} is {{#t}}, {{form}} automatically generates a
1481hidden input field to pass the session identifier (unless
1482{{no-session}} is {{#t}}).
1483
1484
1485===== {{define-login-trampoline}}
1486<procedure>(define-login-trampoline path #!key vhost-root-path hook)</procedure>
1487
1488Define a trampoline -- an intermediate page accessed when redirecting
1489from the login page to the main page.
1490
1491{{vhost-root-path}} is the path to the virtual host the trampoline
1492will be defined for.
1493
1494{{hook}} is a one-argument procedure which receives the given user.
1495It is called right before the redirection to the attempted path (if
1496any was attempted) or {{(main-page-path)}}.
1497
1498
1499===== {{login-form}}
1500<procedure>(login-form #!key (user-label "User: ") (password-label "Password: ") (submit-label "Submit") (refill-user #t) (trampoline-path "/login-trampoline"))</procedure>
1501
1502Return a user/password login form (e.g., for using in authentication pages).
1503
1504When the {{refill-user}} is {{#t}}, the User field is refilled with
1505the value from the {{user}} query string value when either the session
1506or the password is invalid.
1507
1508The {{user-label}}, {{password-label}} and {{submit-label}} keyword
1509parameters are labels to be used for the user, password and submit
1510form widgets, respectively.
1511
1512{{trampoline-path}} is a string that specify the path the form will be
1513submitted to.  It must match the path given as argument to
1514{{define-login-trampoline}}.
1515
1516==== Request variables and values
1517
1518===== {{$}}
1519<procedure>($ var #!optional default/converter)</procedure>
1520
1521Return the HTTP request value for the given variable {{var}}.  The
1522variable is looked for in both the query string (GET method) and
1523request body (e.g., POST method).  See the documentation for the
1524procedure returned by
1525[[/eggref/4/spiffy-request-vars|spiffy-request-vars]]'s
1526{{request-vars}} for further details.
1527
1528
1529===== {{with-request-variables}}
1530<macro>(with-request-variables (var1 var2 ... varn) expression1 ...)</macro>
1531
1532A wrapper around [[/egg/spiffy-request-vars|spiffy-request-vars]]'s
1533{{with-request-vars*}}.
1534
1535All the [[/egg/spiffy-request-vars|spiffy-request-vars]]'s converter
1536procedures are exported, for convenience.
1537
1538
1539==== Database access
1540
1541===== {{$db}}
1542<procedure>($db q #!key (default '()) values)</procedure>
1543
1544Execute the given query ({{q}}) on the database and return the result
1545as a list of lists or {{default}} if the result set is empty.
1546
1547The {{values}} keyword parameter (a list) is a list of values to
1548replace the placeholders in the query.
1549
1550Example:
1551
1552<enscript highlight=scheme>
1553($db "insert into foo (bar, baz) values (?, ?)" values: '("bar-val" "baz-val"))
1554</enscript>
1555
1556''Note'': up to version 0.40.0, {{$db}} returned {{#f}} when queries
1557returned empty set of results.  Starting from version 0.41.0, {{$db}}
1558returns {{'()}} queries return empty set of results.
1559
1560If you use the [[/egg/awful-ssql|awful-ssql]] egg, you can give
1561{{$db}} the query as a SSQL expression.  See the documentation for
1562[[/egg/awful-ssql|awful-ssql]] for more details.  Support for SSQL has
1563been introduced in awful version 0.40.0.
1564
1565Note that {{$db}} is supposed to be used in the context of request
1566handlers (i.e., in the body of a lambda bound to a uri path by
1567{{define-page}}).
1568
1569If you want to use {{$db}} out of the context of request handlers,
1570you'll have to manage database connections yourself.  Basically, you
1571have to parameterize {{db-connection}} with the actual connection
1572object.  Example:
1573
1574<enscript highlight=scheme>
1575(parameterize ((db-connection (open-database (db-credentials))))
1576  ($db the-query)
1577  (close-database (db-connection)))
1578</enscript>
1579
1580
1581===== {{$db-row-obj}}
1582<procedure>($db-row-obj q)</procedure>
1583
1584Execute the given query {{q}} on the database and return an
1585one-argument procedure which takes as argument the name of the
1586database field to get the value.
1587
1588Example:
1589
1590<enscript highlight=scheme>
1591(let ((& ($db-row-obj "select full_name, phone from users where user_id=1")))
1592  (<p> "Full name: " (& 'full_name))
1593  (<p> "Phone: " (& 'phone)))
1594</enscript>
1595
1596''Warning'': currently {{$db-row-obj}} is only implemented for
1597PostgreSQL databases.
1598
1599If you use the [[/egg/awful-ssql|awful-ssql]] egg, you can give
1600{{$db}} the query as a SSQL expression.  See the documentation for
1601[[/egg/awful-ssql|awful-ssql]] for more details.  Support for SSQL has
1602been introduced in awful version 0.40.0.
1603
1604
1605==== Pages
1606
1607===== {{define-page}}
1608<procedure>(define-page path-matcher handler #!key css title doctype headers charset no-ajax use-ajax no-template no-session no-db no-javascript-compression method use-sxml vhost-root-path strict)</procedure>
1609
1610Define an awful page.
1611
1612{{path-matcher}} matches requested paths.  It can be represented by three types:
1613; string: a literal path. When the path matcher is a string, the handler procedure must be a thunk.
1614; regex: a regular expression to match the requested path (regexes created by both regex egg and irregex unit are valid values).  When the path matcher is a regular expression, the page handler procedure must be a one-argument procedure which will be given the requested path.
1615; procedure: a one-argument procedure to match the requested path (feature introduced in awful 0.35). If the procedure matches the requested path, it should return a list to be applied to the page handler.  When the path matcher is a procedure, the arity of the page handler procedure must match the length of the list returned by the path matcher. {{#f}} indicates that there was no match.  Values which are not {{#f}} or a list will cause an invalid argument type error.
1616
1617
1618{{handler}} should return either a string, a no-argument procedure or
1619a list (in case SXML mode is enabled -- SXML support has been
1620introduced in awful 0.36).  If it returns a string, it will be given
1621as argument to {{(page-template)}}, unless {{no-template}} is not
1622false. If {{handler}} returns a procedure (feature introduced in awful
16230.35), awful won't do anything besides evaluating the returned
1624procedure.  It can be useful, for example, to serve static files out
1625of the web server document directory (see the examples in this
1626section). If {{handler}} produces a list, awful or the particular page
1627in question must be operating in SXML mode, which can be set via the
1628{{enable-sxml}} parameter or via de {{use-sxml}} keywork parameter for
1629{{define-page}}.  The list produced by the handler will be given as
1630argument to the procedure yield by the {{sxml->html}} parameter.
1631
1632{{use-sxml}} (boolean): specifies whether awful should assume that the
1633handler produces SXML code or strings.  In case the handler produces
1634SXML code, the parameter {{sxml->html}} yields the procedure used to
1635generate HTML out of SXML.
1636
1637{{method}} (a symbol or a list) indicates the HTTP method to be used
1638(e.g., {{GET}}, {{POST}}, {{PUT}}).  {{method}} can also be a list of
1639methods.  In this case, awful will define a page for each method of
1640the list.  Methods are case-insensitive.  Pages that use different
1641methods can use the same path.  The default value is {{(GET HEAD)}}
1642(prior to version 0.39, the default value was just {{GET}}).
1643
1644The {{css}}, {{title}}, {{doctype}}, {{headers}} and {{charset}}
1645keyword parameters have the same meaning as {{html-page}} (from the
1646[[/egg/html-utils|html-utils]] egg).
1647
1648If {{no-ajax}} is {{#t}}, it means that the page won't use ajax, even
1649if the {{enable-ajax}} parameter is {{#t}}.
1650
1651If {{use-ajax}} is {{#t}}, it means that the page will be linked to
1652the ajax library, even if the {{enable-ajax}} parameter is {{#f}}.
1653
1654If {{no-template}} is {{#t}}, it means that no page template (see the
1655{{page-template}} parameter) should be used.
1656
1657If {{no-session}} is {{#t}}, it means that the page should not use session.
1658
1659If {{no-db}} is {{#t}}, it means that the page should not use the
1660database, even when database usage is activated by {{enable-db}} and
1661{{db-credentials}} is not {{#f}}.
1662
1663If {{no-javascript-compression}} is {{#t}} the JavaScript code for the
1664page is not compressed, even when {{enable-javascript-compression}} is
1665not {{#f}}.
1666
1667{{vhost-root-path}} (a string or {{#f}}) is the root path of the
1668virtual host the page definition is to be applied to.  If
1669{{vhost-root-path}} is set to a path, the page definition will only be
1670valid for the virtual host whose root path is the given path.
1671
1672If {{strict}} is truthy, awful will only match the requested path if
1673it strictly matches the defined matchers.  For convenience, awful
1674sloppily considered requests for files and directories to be
1675equivalent.  For example, if a page was defined with a {{"/foo"}}
1676matcher, a request for {{"/foo/"}} would be handled by {{"/foo"}}'s
1677handler.  That's not always desired.  For example, consider this case:
1678
1679  (define-page (irregex "/[^/]*") identity)
1680
1681We want to specify that, e.g., requests for {{/foo}} should be
1682handled, but requests for {{/foo/}} should ''not'' be handled.  However,
1683since awful tries to find a handler by stripping the trailing slash, a
1684request for {{/foo/}} would actually be handled by the handler for
1685{{(irregex "/[^/]*")}}, even if the regex specified that paths with a
1686trailing slash should not match.
1687
1688Examples:
1689
1690<enscript highlight=scheme>
1691(cond-expand
1692  (chicken-4
1693    (use awful
1694         srfi-1   ;; for filter-map
1695         srfi-13  ;; for string-prefix?
1696         irregex  ;; for irregex
1697         spiffy)) ;; for send-static-file
1698  (chicken-5
1699    (import (chicken irregex) ;; for irregex
1700            (chicken format)  ;; for sprintf
1701            (chicken string)) ;; for string-split
1702    (import awful
1703            srfi-1   ;; for filter-map
1704            srfi-13  ;; for string-prefix?
1705            spiffy)) ;; for send-static-file
1706  )
1707
1708;;
1709;; Path matcher as a string
1710;;
1711
1712;; http://host:port/foo => "bar"
1713(define-page "/foo"
1714  (lambda ()
1715    "bar"))
1716
1717
1718;;
1719;; Path matcher as a regular expression
1720;;
1721
1722;; http://host:port/add/1/2/3 => 6
1723(define-page (irregex "/add/.*")
1724  (lambda (path)
1725    (let ((numbers (filter-map string->number (string-split path "/"))))
1726      `(,(apply + numbers)))))
1727
1728
1729;;
1730;; Path matchers as procedures
1731;;
1732
1733(define (ticket-id path)
1734  (and (string-prefix? "/ticket/" path)
1735       (and-let* ((tokens (string-split path "/"))
1736                  (_ (not (null? (cdr tokens))))
1737                  (id (string->number (cadr tokens))))
1738         (and id (list id)))))
1739
1740
1741(define (ticket-reporter+severity path)
1742  (and (string-prefix? "/ticket/" path)
1743       (and-let* ((tokens (string-split path "/"))
1744                  (_ (> (length tokens) 2)))
1745         (list (cadr tokens)
1746               (caddr tokens)))))
1747
1748;; http://host:port/ticket/4
1749(define-page ticket-reporter+severity
1750  (lambda (reporter severity)
1751    `(,(sprintf "Reporter=~a, severity=~a"
1752                reporter
1753                severity))))
1754
1755;; http://host:port/ticket/4/5
1756(define-page ticket-id
1757  (lambda (id)
1758    `("This is ticket " ,id)))
1759
1760
1761;;
1762;; Page handler returning a procedure
1763;;
1764
1765;; Serving a static file out of the web server documents directory
1766(define-page "/my-dot-emacs"
1767  (lambda ()
1768    (lambda ()
1769      (parameterize ((root-path (get-environment-variable "HOME")))
1770        (send-static-file ".emacs"))))
1771  no-template: #t)
1772</enscript>
1773
1774
1775===== {{define-session-page}}
1776<procedure>(define-session-page path-matcher handlerr . rest)</procedure>
1777
1778Define a session-aware page.  When the page is accessed and a
1779corresponding session does not exist, it is created.  If the session
1780already exists and is not valid, it is recreated.  If the session
1781already exists and is valid, then it is refreshed.
1782
1783The {{rest}} parameters are the same as for {{define-page}}.
1784
1785Here's an example (the [[http://www.paulgraham.com/arcchallenge.html|arc challenge]]):
1786
1787<enscript highlight=scheme>
1788(cond-expand
1789  (chicken-4
1790    (use awful))
1791  (chicken-5
1792    (import awful)))
1793
1794(define-session-page "said"
1795  (lambda ()
1796    (with-request-variables (said)
1797      (cond (said
1798             ($session-set! 'said said)
1799             `(,(link "said" "click here")))
1800            (($session 'said)
1801             => (lambda (said)
1802                  `("You said: " ,said)))
1803            (else `(,(form '((input (@ (type "text") (name "said")))
1804                             (input (@ (type "submit"))))
1805                           action: "said"
1806                           method: 'post))))))
1807  method: '(GET POST))
1808</enscript>
1809
1810
1811===== {{undefine-page}}
1812<procedure>(undefine-page path #!optional vhost-root-path)</procedure>
1813
1814Undefine a page whose path is {{path}} (a string or a regular
1815expression object).
1816
1817The optional parameter {{vhost-root-path}} is the path of virtual host
1818where the page is to be undefined.  If omitted, {{(root-path)}} is
1819used.
1820
1821
1822===== {{set-page-title!}}
1823<procedure>(set-page-title! title)</procedure>
1824
1825Set the title for the requested page.  This procedure is useful to set
1826the page title dynamically from the page handler (instead of
1827statically, via {{define-page}}'s {{title}} keyword parameter).
1828
1829This procedure has been introduced in awful 0.35.
1830
1831Example:
1832
1833<enscript highlight=scheme>
1834(cond-expand
1835  (chicken-4
1836    (use awful))
1837  (chicken-5
1838    (import awful)))
1839
1840(define-page (main-page-path)
1841  (lambda ()
1842    (set-page-title! "a title")
1843    "Hi!"))
1844</enscript>
1845
1846
1847===== {{html-page}}
1848
1849<procedure>(html-page contents #!key css title doctype headers charset content-type literal-style? (html-attribs '()) (body-attribs '()))</procedure>
1850
1851Generates an SXML page containing {{contents}} (SXML).  The following
1852keywords arguments may be used to customize the page:
1853
1854* {{headers}}: an SXML form containing additional headers to be inserted in the section delimited by the {{<head>}} tag. Default = {{#f}}.
1855
1856* {{title}}: the title for the page (to be used in the {{<title>}} tag). Default = {{#f}}.
1857
1858* {{css}}: may be either a path to a Cascading Style Sheet file, to be linked from the generated page (the default value is {{#f}}, so no CSS is used) or a list of paths to CSS files. If a list of paths is used, the elements which are also lists are read and inlined into the generated page. Example: {{css: '("css1.css" ("css2.css"))}}. In the example, {{css1.css}} would be linked from the generated page (using the link tag) and {{css2.css}} would be inlined into the generated page (e.g., {{html-page}} would read the {{css2.css}} file and inline its contents in the HTML code).
1859
1860* {{doctype}}: specifies the document type of the generated page. The default value is {{#f}}. The possible values are the ones available from the [[doctype]] egg.
1861
1862* {{charset}}: specifies the default charset to be used in the corresponding meta tag of the document. The default value is {{"UTF-8"}} (only when {{content-type}} is provided).
1863
1864* {{literal-style?}}: if {{#f}}, convert special characters in style code (CSS) to theyr equivalent HTML entities.  If non-{{#f}}, insert them verbatim.
1865
1866* {{content-type}} and {{charset}} are used together for the {{<meta http-equiv ...>}} specification.: {{charset}}'s default value is {{"UTF-8"}} and {{content-type}}'s default value is {{"application/xhtml+xml"}}.
1867
1868* {{html-attribs}}: attributes to the {{html}} tag. The format is a list of lists {{(<attribute> <value>)}} ({{<attribute>}} is a symbol).  Example: {{(html-page "foo" html-attribs: '((lang "us")))}}.
1869
1870* {{body-attribs}}: attributes to the {{body}} tag. The format is a list of lists {{(<attribute> <value>)}} ({{<attribute>}} is a symbol).  Example: {{(html-page "foo" body-attribs: '((bgcolor "red")))}}.
1871
1872
1873
1874==== Ajax
1875
1876===== {{ajax}}
1877<procedure>(ajax path selector event proc #!key target (action 'html) (method 'POST) (arguments '()) success no-session no-db vhost-root-path live on prelude update-targets cache error-handler use-sxml strict)</procedure>
1878
1879Generate JavaScript code to be added to the page defined by
1880{{define-page}}.  Return the generated JavaScript code. Unless
1881{{no-page-javascript}} is a truthy value, the JavaScript code will be
1882added to the page in which case the returned JavaScript code is
1883usually not useful and can be discarded.
1884
1885{{path}} is the URL path (a string) of the server side handler. This
1886path is placed under the {{(app-root-path)/(ajax-namespace)}} path.
1887So, if your {{app-root-path}} is {{"my-app"}}, your {{ajax-namespace}}
1888is {{"ajax"}} and you use {{"do-something"}} as the first argument to
1889{{ajax}}, the URL for the server side handler would be
1890{{"/my-app/ajax/do-something"}}.
1891
1892{{selector}} is the selector for the DOM element to be observed.  If
1893it is a quoted symbol, awful generates a jQuery selector by DOM id
1894(e.g., {{'my-selector}} generates {{"#my-selector"}}).  If it is a
1895string, awful uses it as-is to generate the jQuery selector (e.g.,
1896{{"input[name^=omg]"}} generates {{"input[name^=omg]"}}).
1897
1898{{event}} (a quoted symbol or a list) is the event(s) to be
1899observed. If it is a quoted symbol (e.g., {{'click}}), only this event
1900will be bound.  If {{event}} is a list of events, all the events from
1901the list will be bound.
1902
1903{{proc}} is a no-argument procedure to be executed on the server side.
1904
1905The {{target}} keyword parameter is the id of the DOM element to be
1906affected by the result of {{proc}}.
1907
1908The {{method}} (a quoted symbol, usually {{'GET}} or {{'POST}})
1909keyword parameter is the HTTP method to be used by the ajax request.
1910
1911The {{arguments}} keyword parameter is an alist mapping request
1912variables (symbols) to their values (strings).  {{ajax}} uses these
1913arguments to assembly the query string or the request body to send to
1914the server when performing the ajax request.
1915
1916If {{use-sxml}} is {{#t}}, it specifies that the ajax handler produces
1917SXML code instead of strings.
1918
1919
1920Example:
1921
1922<enscript highlight=scheme>
1923arguments: '((var1 . "$('#var1').val()")
1924             (var2 . "$('#var2').val()"))
1925</enscript>
1926
1927If the {{no-session}} keyword parameter is {{#t}}, it means that no
1928session should be considered ({{ajax}} implicit sends the session
1929identifier when {{no-session}} is {{#f}}).
1930
1931If the {{no-db}} keyword parameter is {{#t}}, it means that the should
1932be no attempt to connect the database, even when database usage is
1933activated by {{enable-db}} and {{db-credentials}} is not {{#f}}.
1934
1935The {{vhost-root-path}} keyword parameter (a string) is the vhost root
1936path.  It is useful for explicitly separate pages defined using the
1937same path (see {{define-page}}) but for different vhosts.
1938
1939The {{on}} keyword parameter (boolean) indicates whether ajax should
1940use jQuery's {{on}} method (see [[http://api.jquery.com/on/]]).  If
1941{{on}} gets bound to {{#t}}, awful will generate code to start
1942delegating events from the {{document}} DOM element.  If {{on}} gets
1943bound to a symbol, awful will generate code to start delegating events
1944from DOM element whose id is the given symbol.  If {{on}} gets bound
1945to a string, awful will generate code to start delegating events from
1946DOM element which matches the given string representing a
1947selector. The {{on}} keyword parameter was introduced in awful 0.39.2.
1948
1949The {{live}} keyword parameter (boolean) indicates whether ajax should
1950use jQuery's {{live}} method (see
1951[[http://api.jquery.com/live/]]). Note that the {{live}} method was
1952deprecated in jQuery 1.7 and removed in version 1.9.  If you are using
1953a more recent version of jQuery, see the {{on}} keyword parameter for
1954{{ajax}} (introduced in awful 0.39.2).
1955
1956The {{prelude}} keyword parameter (string) is an arbitrary piece of
1957JavaScript code to be placed right before the ajax request.
1958
1959The {{update-targets}} keyword parameter a boolean indicating whether
1960multiple targets should be updated upon ajax response.  When
1961{{update-targets}} is used, the procedure {{proc}} used as argument to
1962{{ajax}} should yield an alist as result.  The alist maps DOM elements
1963identifiers to their corresponding values.
1964
1965Here's an example:
1966
1967<enscript highlight=scheme>
1968(cond-expand
1969  (chicken-4
1970    (use awful))
1971  (chicken-5
1972    (import awful)))
1973
1974(define-page (main-page-path)
1975  (lambda ()
1976
1977    (ajax "foo" 'foo 'click
1978          (lambda ()
1979            '((a . 1) (b . 2) (c . 3)))
1980          update-targets: #t)
1981
1982    `(,(link "#" "Click me" id: "foo")
1983      (div (@ (id "a")))
1984      (div (@ (id "b")))
1985      (div (@ (id "c")))))
1986  use-ajax: #t)
1987</enscript>
1988
1989The {{success}} keyword parameter (string) can be any arbitrary
1990JavaScript code to be executed on the successful ajax request.  The
1991JavaScript code can assume that a variable {{response}} is bound and
1992contains the request resulting data.  Here's an example:
1993
1994<enscript highlight=scheme>
1995(cond-expand
1996  (chicken-4
1997    (use awful))
1998  (chicken-5
1999    (import awful)))
2000
2001(define-page (main-page-path)
2002  (lambda ()
2003
2004    (ajax "foo" 'foo "click"
2005          (lambda ()
2006            "hey")
2007          success: "$('#bar').html(response + ' you!')")
2008
2009    `(,(link "#" "Click me" id: "foo")
2010      (div (@ (id "bar")))))
2011  use-ajax: #t)
2012</enscript>
2013
2014The {{cache}} keyword parameter (boolean), if set to {{#f}}, it will
2015force requested pages not to be cached by the browser.  The default
2016value is not set, leaving it to be set by jQuery. See
2017[[http://api.jquery.com/jQuery.ajax/|jQuery's documentation]] for
2018further details.
2019
2020The {{error-handler}} keyword parameter expects a JavaScript callback
2021to be used as the error handler for the Ajax request.  See the
2022{{error}} attribute for the {{settings}} object given as argument to
2023jQuery.ajax
2024([[http://api.jquery.com/jQuery.ajax/|http://api.jquery.com/jQuery.ajax/]]).
2025
2026The {{no-page-javascript}} keyword parameter is a boolean that
2027determines whether the generated JavaScript code is automatically
2028added to the page or not.  Defaults to {{#f}}. This parameter may be
2029useful if you want more control of where or when the generated
2030JavaScript code gets added to the page or even if it gets added at
2031all.
2032
2033The {{ajax}} procedure is session, HTTP request and database -aware.
2034
2035
2036===== {{periodical-ajax}}
2037<procedure>(periodical-ajax path interval proc #!key target (action 'html) (method 'POST) (arguments '()) success no-session no-db vhost-root-path live on prelude update-targets error-handler use-sxml strict)</procedure>
2038
2039Periodically execute {{proc}} on the server side, using
2040{{(app-root-path)/(ajax-namespace)/path}} as the URL path for the
2041server side handler.
2042
2043{{interval}} (a number) is the interval between consecutive executions
2044of {{proc}}, in milliseconds.
2045
2046The meaning of the keyword parameters is the same as for {{ajax}}'s.
2047
2048
2049===== {{ajax-link}}
2050<procedure>(ajax-link path id text proc #!key target (action 'html) (method 'POST) (arguments '()) success no-session no-db (event 'click) vhost-root-path live on class hreflang type rel rev charset coords shape accesskey tabindex a-target prelude update-targets error-handler use-sxml strict)</procedure>
2051
2052A shortcut to
2053
2054<enscript highlight=scheme>
2055(begin
2056  (ajax path id 'click proc ...)
2057  (<a> href: "#" [...other <a> keyword parameters...] id: id text))
2058</enscript>
2059
2060The meaning of the {{target}}, {{action}}, {{method}}, {{arguments}},
2061{{success}}, {{no-session}}, {{no-db}}, {{event}},
2062{{vhost-root-path}}, {{update-targets}} {{live}} and {{on}} keyword
2063parameters is the same as for {{ajax}}'s.
2064
2065The meaning of the {{class}}, {{hreflang}}, {{type}}, {{rel}},
2066{{rev}}, {{charset}}, {{coords}}, {{shape}}, {{accesskey}},
2067{{tabindex}} and {{a-target}} are the same as for
2068[[/egg/html-tags|html-tags]]' {{<a>}} procedure (except that
2069{{a-target}} is {{<a>}}'s {{target}}, since {{ajax}} uses the
2070{{target}} keyword parameter).
2071
2072The {{event}} keyword parameter syntax is the same for {{ajax}}'s
2073{{event}} mandatory parameter.
2074
2075
2076==== Redirection
2077
2078===== {{redirect-to}}
2079<procedure>(redirect-to uri)</procedure>
2080
2081Perform an HTTP redirection (code 302) to the given {{uri}} (either a
2082string or a [[/eggref/4/uri-common|uri-common]] URI object).  To be
2083used from {{define-page}} handler.  Example:
2084
2085<enscript highlight=scheme>
2086(cond-expand
2087  (chicken-4
2088    (use awful))
2089  (chicken-5
2090    (import awful)))
2091
2092;; / -> /foo
2093(define-page "/"
2094  (lambda ()
2095    (redirect-to "/foo")))
2096
2097(define-page "/foo"
2098  (lambda ()
2099    "foo"))
2100</enscript>
2101
2102The example above shows a redirection from {{/}} to {{/foo}}.
2103Redirections can also be performed when the origin path is a regular
2104expression:
2105
2106<enscript highlight=scheme>
2107(cond-expand
2108  (chicken-4
2109    (use awful))
2110  (chicken-5
2111    (import awful)))
2112
2113;; /bar.* -> /foo
2114(define-page (regexp "/bar.*")
2115  (lambda (_)
2116    (redirect-to "/foo")))
2117
2118(define-page "/foo"
2119  (lambda ()
2120    "foo"))
2121</enscript>
2122
2123
2124==== Request handler hooks
2125
2126Awful provides the possibility of plugin hooks to the request handler,
2127so that deploying multiple awful applications under the same virtual
2128host is possible and easy.
2129
2130===== {{add-request-handler-hook!}}
2131<procedure>(add-request-handler-hook! hook-id proc)</procedure>
2132
2133Adds a hook identified by {{id}} (can be used to remove the hook if
2134necessary). {{proc}} is a two-argument procedure which receives the
2135requested path and its handler.
2136
2137Here's a simple usage example:
2138
2139<enscript highlight=scheme>
2140(add-request-handler-hook!
2141 'foo
2142 (lambda (path handler)
2143   (when (string-prefix? "/foo" path)
2144     (parameterize
2145         ((debug-file "/tmp/foo-debug")
2146          (enable-ajax #t))
2147       (handler))))
2148</enscript>
2149
2150By using request handlers, you can parameterize parameter values in a
2151way that they don't affect other applications.
2152
2153===== {{remove-request-handler-hook!}}
2154<procedure>(remove-request-handler-hook! hook-id)</procedure>
2155
2156Removes the request handler hook identified by {{id}}.
2157
2158
2159==== Web REPL
2160
2161===== {{enable-web-repl}}
2162<procedure>(enable-web-repl path #!key css title)</procedure>
2163
2164Enable the web REPL.  {{path}} is the URL path to the web REPL.
2165
2166The keyword parameter {{css}} is the CSS to be used the the web REPL
2167page (see the documentation for {{html-page}}, from the
2168[[/egg/html-utils|html-utils]] egg, for the {{css}} keyword
2169parameter.)
2170
2171The keyword parameter {{title}} (a string) is the title for the web
2172REPL page (see the documentation for {{html-page}}, from the
2173[[/egg/html-utils|html-utils]] egg, for the {{title}} keyword
2174parameter.)
2175
2176The web REPL is automatically enabled by the awful application server
2177when the {{--development-mode}} is provided (available from
2178{{/web-repl}}).  By default, the fancy editor is used, but can be
2179disabled with the {{--disable-web-repl-fancy-editor}} command line
2180option for the awful application server.
2181
2182
2183==== Session inspector
2184
2185===== {{enable-session-inspector}}
2186<procedure>(enable-session-inspector path #!key css title)</procedure>
2187
2188Enable the session inspector.  {{path}} is the URL path to the session
2189inspector.
2190
2191The keyword parameter {{css}} is the CSS to be used the the session
2192inspector page (see the documentation for {{html-page}}, from the
2193[[/egg/html-utils|html-utils]] egg, for the {{css}} keyword
2194parameter.)
2195
2196The keyword parameter {{title}} (a string) is the title for the
2197session inspector page (see the documentation for {{html-page}}, from
2198the [[/egg/html-utils|html-utils]] egg, for the {{title}} keyword
2199parameter.)
2200
2201The session inspector is automatically enabled by the awful
2202application server when the {{--development-mode}} is provided
2203(available from {{/session-inspector}}).
2204
2205
2206==== Applications
2207
2208===== {{load-apps}}
2209<procedure>(load-apps apps)</procedure>
2210
2211Load the given applications ({{apps}} - a list) (using
2212[[/man/4/Unit eval#load|load]]).
2213
2214
2215===== {{reload-apps}}
2216<procedure>(reload-apps apps)</procedure>
2217
2218The same as {{load-apps}} but also reseting the resources table (the
2219thing that maps URIs to procedures) before loading applications.
2220
2221
2222==== The awful server
2223
2224===== {{awful-start}}
2225<procedure>(awful-start thunk #!key dev-mode? port ip-address (use-fancy-web-repl? #t) privileged-code))</procedure>
2226
2227Starts awful.  This procedure is only useful for standalone
2228applications which intent to embed awful.  For example, the awful
2229application server (the awful command line tool) uses it.
2230
2231This procedure does all the listening, switching user/group and
2232entering the accept loop dance.
2233
2234{{thunk}} is a procedure to be executed upon starting awful.  It can
2235be Scheme code just like any other that can be loaded as an awful
2236application.
2237
2238{{dev-mode?}} (boolean) indicates whether awful should run in development mode.
2239
2240{{port}} (integer) indicates to port to bind to.
2241
2242{{ip-address}} (string) indicates the IP address to bind to.
2243
2244{{use-fancy-web-repl?}} (boolean): indicates whether the web REPL
2245should use the fancy editor.  The default value is {{#t}} (since awful
22460.40.0 -- before that it was {{#f}})
2247
2248{{privileged-code}} (procedure): a thunk that is executed while awful
2249is still running with privileged permissions (when run by the
2250superuser).
2251
2252=== List of macros
2253
2254==== Applications definition
2255
2256===== define-app
2257<syntax>(define-app id matcher: matcher [ parameters: parameters | handler-hook: handler-hook ] body ...)</syntax>
2258
2259This macro can be used to define an awful application. It's a wrapper
2260around {{add-request-handler-hook!}} and should be used when you have
2261multiple awful applications running under the same server, so
2262parameters set for one application don't interfere with other
2263applications' parameters.
2264
2265The idea is that the application's matcher controls when the given
2266parameters or handler-hook will be applied to take effect over the
2267given body expressions.
2268
2269{{id}} (a symbol) is an identifier for the application.
2270
2271{{matcher}} is a Scheme object that is matched against requested
2272paths.  When there is a match, the given parameters or handler-hook
2273are bound/evaluated during the evaluation of {{body}}.  The following
2274types are supported:
2275
2276; lists of strings : lists of strings can be used to represent paths to be matched against requested paths.  For example, if the matcher is {{'("/" "/foo")}}, it'll match requests for {{"/foo"}} and {{"/foo/"}}.
2277
2278; one-argument procedures : if the matcher is a one-argument procedure, it will be given the requested path as argument.  If it returns a non-{{#f}} value, it indicates a match.
2279
2280; a regular expression object : if the matcher is a regular expression object (e.g., {{(regexp "/foo.*")}}), awful will try to match the requested path against the given regex.
2281
2282
2283{{parameters}} and {{handler-hook}} are mutually exclusive and
2284optional.
2285
2286{{parameters}} is a list of parameter bindings (same syntax as the
2287list given as first argument to {{parameterize}}) that are bound when
2288body is evaluated.
2289
2290{{handler-hook}} is a one-argument procedure which is given the
2291request handler continuation. It is more flexible than {{parameters}},
2292since it can do anything before {{body}} is evaluated, including
2293setting parameters (e.g., using {{parameterize}}).
2294
2295Notice that {{matcher}}, {{parameters}} and {{handler-hook}} are not
2296keyword parameters, they are part of {{define-app}}'s syntax.
2297
2298{{body}} represents the expressions to be evaluated when matcher
2299returns a truthy value.
2300
2301Notice that {{define-app}}'s matcher does not affect the
2302'''definition''' of pages -- they are defined just as if they were
2303defined outside {{define-app}}'s body.
2304
2305Here are some examples, assuming we have three applications, foo, bar
2306and baz, running on the same awful server. The way we "separate"
2307applications is by checking the path prefix, so foo is available from
2308{{/foo}}, bar from {{/bar}} and baz from {{/baz}}. Other criteria can
2309be used, but for simplicity, we'll just use path prefixes.
2310
2311<enscript highlight=scheme>
2312(cond-expand
2313  (chicken-4
2314    (use awful awful-sql-de-lite srfi-13))
2315  (chicken-5
2316    (import awful awful-sql-de-lite srfi-13)))
2317
2318
2319;;;
2320;;; App foo
2321;;;
2322(define-app foo
2323  matcher: (lambda (path)
2324             (string-prefix? "/foo" path))
2325
2326  parameters: ((enable-ajax #t)
2327               (ajax-library "/js/foo.js"))
2328
2329  (define-page "/foo/baz"
2330    (lambda ()
2331      '(p "baz from foo")))
2332
2333  (define-page "/foo/quux"
2334    (lambda ()
2335      '(p "quux from foo")))
2336
2337)
2338
2339;;;
2340;;; App bar
2341;;;
2342(define-app bar
2343  matcher: (lambda (path)
2344             (string-prefix? "/bar" path))
2345
2346  handler-hook: (lambda (handler)
2347                  (switch-to-sql-de-lite-database)
2348                  (parameterize ((enable-ajax #t)
2349                                 (ajax-library "/js/bar.js")
2350                                 (db-credentials "/var/bar/bar.db"))
2351                    (handler)))
2352
2353  (define-page "/bar/baz"
2354    (lambda ()
2355      '(p "baz from bar")))
2356
2357  (define-page "/bar/quux"
2358    (lambda ()
2359      '(p "quux from bar")))
2360
2361)
2362
2363;;;
2364;;; App baz
2365;;;
2366(define-app baz
2367  matcher: (lambda (path)
2368             (string-prefix? "/baz" path))
2369
2370  (define-page "/baz/foo"
2371    (lambda ()
2372      '("foo from baz")))
2373
2374  (define-page "/baz/bar"
2375    (lambda ()
2376      '("bar from baz")))
2377
2378)
2379</enscript>
2380
2381=== Tips and tricks
2382
2383==== Reload applications' code on every request
2384
2385You can use {{add-request-handler-hook!}} to reload the applications'
2386code every time a request is handled by awful.  Here's a simple
2387example:
2388
2389<enscript highlight=scheme>
2390(cond-expand
2391  (chicken-4
2392    (use awful))
2393  (chicken-5
2394    (import awful)))
2395
2396(add-request-handler-hook!
2397 'reload-on-request
2398 (lambda (path handler)
2399   (reload-apps (awful-apps))
2400   (handler)))
2401
2402(define-page (main-page-path)
2403  (lambda ()
2404    '("1")))
2405</enscript>
2406
2407
2408==== Use {{link}} and {{form}} for links and forms
2409
2410Instead of using {{<a>}} and {{<form>}} for creating links and forms,
2411respectively, consider using the {{link}} and {{form}} procedures
2412instead.  They are specially useful when using sessions, since they
2413transparently handle the session identifier for you.  Even if you
2414don't use sessions, they may save you some work if one day you decide
2415to use sessions (then you won't have do to anything regarding to links
2416and forms).
2417
2418
2419==== Use {{with-request-variables}} when referencing the same request variable multiple times
2420
2421When you need to access the same request variable more than once,
2422consider using {{with-request-variables}}.
2423
2424For example, instead of:
2425
2426<enscript highlight=scheme>
2427(cond-expand
2428  (chicken-4
2429    (use awful))
2430  (chicken-5
2431    (import awful)))
2432
2433(define-session-page "save-and-show-user"
2434  (lambda ()
2435    ($session-set! 'user ($ 'user))
2436    `("Welcome " ,($ 'user "nobody") "!")))
2437</enscript>
2438
2439consider using something like:
2440
2441<enscript highlight=scheme>
2442(cond-expand
2443  (chicken-4
2444    (use awful))
2445  (chicken-5
2446    (import awful)))
2447
2448(define-session-page "save-and-show-user"
2449  (lambda ()
2450    (with-request-variables (user)
2451      ($session-set! 'user user)
2452      `("Welcome " ,(or user "nobody") "!"))))
2453</enscript>
2454
2455
2456==== Use the web REPL and the session inspector for debugging
2457
2458You can simply use the {{--development-mode}} option for the awful
2459application server to enable the web REPL and the session inspector
2460(when {{enable-session}} is {{#t}}).  The development mode allows
2461access to them for the localhost.  When in development mode, the web
2462REPL and the session inspector are available at the {{/web-repl}} and
2463{{/session-inspector}} paths.
2464
2465If you want further flexibility, you can customize the web REPL and
2466the session inspector.
2467
2468Here's a simple recipe to allow access for your local machine to the
2469web REPL ({{/repl}}) and to the session inspector
2470({{/session-inspector}}).
2471
2472<enscript highlight=scheme>
2473(session-inspector-access-control
2474 (lambda ()
2475   (member (remote-address) '("127.0.0.1"))))
2476
2477(enable-session-inspector "/session-inspector")
2478
2479
2480(web-repl-access-control
2481 (lambda ()
2482   (member (remote-address) '("127.0.0.1"))))
2483
2484(enable-web-repl "/repl")
2485</enscript>
2486
2487To access them, just point your browser to
2488{{http://localhost:<port>/repl}} and
2489{{http://localhost:<port>/session-inspector}}, respectively.
2490
2491
2492==== Create custom page definers when {{page-template}} and/or plain {{define-page}} are not enough
2493
2494You can define your own page definers when {{page-template}} or the
2495plain {{define-page}} is not enough for what you need.  Here's an
2496example:
2497
2498<enscript highlight=scheme>
2499(cond-expand
2500  (chicken-4
2501    (use awful))
2502  (chicken-5
2503    (import awful)))
2504
2505(define (define-custom-page path content)
2506  (define-page path
2507    (lambda ()
2508      `(html (body ,(content))))
2509    no-template: #t))
2510
2511(define-custom-page (main-page-path)
2512  (lambda ()
2513    '("Hey!")))
2514</enscript>
2515
2516If you access {{http://localhost:8080}} you'll get the following HTML code:
2517
2518  <html>
2519  <body>Hey!</body></html>
2520
2521
2522==== Debugging: error messages on the browser window
2523
2524Error messages right on the browser window can be quite handy for
2525debugging (although not for production environments).  Here's a way to
2526accomplish that:
2527
2528<enscript highlight=scheme>
2529(cond-expand
2530  (chicken-4
2531    (use awful))
2532  (chicken-5
2533    (import (chicken base)
2534            (chicken condition)
2535            (chicken port))
2536    (import awful)))
2537
2538(page-exception-message
2539 (lambda (exn)
2540   `(pre ,(with-output-to-string
2541            (lambda ()
2542              (print-call-chain)
2543              (print-error-message exn))))))
2544
2545(define-page (main-page-path)
2546  (lambda ()
2547    `("Boom!" ,(+ 1 "foo"))))
2548</enscript>
2549
2550This feature is automatically enabled when the awful application
2551server is used with the {{--development-mode}} option.
2552
2553
2554
2555==== Run awful without arguments to quickly share a file
2556
2557When invoked without arguments, awful (the application) starts the web
2558server using the current directory as root path and keeps listening on
2559port 8080.  So, if you want to quickly share a file (or some files),
2560change to the directory containing the files and execute {{awful}}.
2561The access {{http://<host>:8080/<the-file-you-want>}}.
2562
2563
2564
2565==== Reloading awful from Emacs
2566
2567Here's a quick hack to reload awful apps from Emacs.  It can be handy
2568when you are developing using awful in development mode
2569({{--development-mode}}, or when you defined your own reload path).
2570
2571<enscript highlight=elisp>
2572(defun awful-reload ()
2573  (interactive)
2574  (shell-command "lynx -dump http://localhost:8080/reload"))
2575
2576(add-hook 'scheme-mode-hook
2577   #'(lambda ()
2578       (local-set-key "\C-cR" 'awful-reload)))
2579</enscript>
2580
2581The code above defines an {{awful-reload}} procedure, which requests
2582the {{/reload}} path (automatically defined by awful when running in
2583development mode) using {{lynx}}.  You can use whatever command line
2584HTTP client you want. {{lynx}} is handy because of the {{-dump}}
2585option, which can be readly displayed by Emacs in the shell command
2586output buffer.
2587
2588Here's a screenshot:
2589
2590[[image://parenteses.org/mario/img/awful/awful-reload-emacs.png|Reloading awful apps from Emacs]]
2591
2592
2593==== Performance tweaks
2594
2595* if you don't intend to use static index files, you may configure the
2596[[/egg/spiffy|Spiffy]] {{index-files}} parameter to {{'()}}.  That
2597will disable the lookup for static index files (or you can configure
2598it to contain only the static index files you use).
2599
2600* awful usually performs better with a larger stack size (1MB is a
2601reasonable value).  You can set the runtime stack size with the
2602{{-:s}} command line option (see
2603[[/manual/Using the compiler#runtime-options|the CHICKEN manual
2604page]] for other options):
2605
2606  $ awful -:s1m my-app.so
2607
2608
2609
2610==== Binding URI paths as arguments to page handler procedures
2611
2612<enscript highlight=scheme>
2613(cond-expand
2614  (chicken-4
2615    (use awful irregex srfi-13))
2616  (chicken-5
2617    (import (chicken string))
2618    (import awful irregex srfi-13)))
2619
2620(define (define-page* page-path content)
2621  (define-page (irregex (string-append page-path "/*.*"))
2622    (lambda (path)
2623      (let ((url-args
2624             (string-split
2625              ;; Removing `page-path' from the requested path
2626              (string-drop path (string-length page-path))
2627              "/")))
2628        (condition-case
2629         (apply content url-args)
2630         ((exn arity) "invalid arity")
2631         (exn () (signal exn)))))))
2632
2633
2634;;;
2635;;; /page1 ignores all arguments
2636;;;
2637;; http://<server>:<port>/page1 => "no args"
2638;; http://<server>:<port>/page1/1 => "no args"
2639;; http://<server>:<port>/page1/1/2 => "no args"
2640(define-page* "/page1"
2641  (lambda _
2642    '("no args")))
2643
2644
2645;;;
2646;;; /page2 requires exactly one argument
2647;;;
2648;; http://<server>:<port>/page2 => "invalid arity"
2649;; http://<server>:<port>/page2/1 => "foo=1"
2650;; http://<server>:<port>/page1/1/2 => "invalid arity"
2651(define-page* "/page2"
2652  (lambda (foo)
2653    '("foo=" foo)))
2654
2655
2656;;;
2657;;; /page3 requires one argument (the other is optional).  Ignores the
2658;;; rest.
2659;;;
2660;; http://<server>:<port>/page3 => "invalid arity"
2661;; http://<server>:<port>/page3/1 => "foo=1, bar=#f"
2662;; http://<server>:<port>/page1/1/2 => "foo=1, bar=2"
2663;; http://<server>:<port>/page1/1/2/3 => "foo=1, bar=2"
2664(define-page* "/page3"
2665  (lambda (foo #!optional bar)
2666    '("foo=" foo ", bar=" bar)))
2667
2668
2669;;;
2670;;; /page4: all arguments are optional (get bound if given).
2671;;;
2672;; http://<server>:<port>/page4 => "foo=#f, bar=#f"
2673;; http://<server>:<port>/page4/1 => "foo=1, bar=#f"
2674;; http://<server>:<port>/page4/1/2 => "foo=1, bar=2"
2675;; http://<server>:<port>/page4/1/2/3 => "foo=1, bar=2"
2676(define-page* "/page4"
2677  (lambda (#!optional foo bar)
2678    '("foo=" foo ", bar=" bar)))
2679</enscript>
2680
2681
2682==== Awful badge
2683
2684Here's a suggestion:  [[image://parenteses.org/mario/img/thats-awful.png|That's awful!]]
2685
2686=== Examples
2687
2688Here are some simple examples using assorted awful features.
2689
2690==== Example with AngularJS
2691
2692Assuming you have
2693[[https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js|angular.min.js]]
2694in the {{root-path}} (the current directory, by default) and the code
2695below is in a file {{angular-app.scm}}:
2696
2697<enscript highlight=scheme>
2698(cond-expand
2699  (chicken-4
2700    (use awful))
2701  (chicken-5
2702    (import awful)))
2703
2704(define-page (main-page-path)
2705  (lambda ()
2706    (html-page
2707     `(div (@ (class "container"))
2708           "Name: " (input (@ (type "text")
2709                              (ng-model "name")))
2710           "{{ name }}")
2711     html-attribs: '((ng-app))
2712     doctype: "<!DOCTYPE html>"
2713     headers: (include-javascript "/angular.min.js")))
2714  no-template: #t)
2715</enscript>
2716
2717Alternatively, you can set the {{page-template}} parameter:
2718
2719<enscript highlight=scheme>
2720(cond-expand
2721  (chicken-4
2722    (use awful))
2723  (chicken-5
2724    (import awful)))
2725
2726;; Configure page-template to set ng-app as attribute for the html tag
2727(page-template
2728 (lambda (content . args)
2729   (apply html-page
2730          (append (list content html-attribs: '((ng-app)))
2731                  args))))
2732
2733(define-page (main-page-path)
2734  (lambda ()
2735    `((div (@ (class "container"))
2736           "Name: " (input (@ (type "text")
2737                              (ng-model "name")))
2738           "{{ name }}")))
2739  doctype: "<!DOCTYPE html>"
2740  headers: (include-javascript "/angular.min.js"))
2741</enscript>
2742
2743To run the example, execute:
2744
2745  $ awful angular-app.scm
2746
2747and use your favorite web browser to access
2748{{http://localhost:8080/}}.
2749
2750
2751==== Number guessing game
2752
2753A screencast showing this example is available at
2754[[http://parenteses.org/mario/awful/awful-guess.ogv|http://parenteses.org/mario/awful/awful-guess.ogv]]
2755
2756This examples shows a simple guessing game. A random number is
2757generated on the server side and the user tries to guess it.  It shows
2758some basic ajax features.
2759
2760<enscript highlight=scheme>
2761(cond-expand
2762  (chicken-4
2763    (use awful))
2764  (chicken-5
2765    (import awful)))
2766
2767(define (prompt-guess)
2768  '(input (@ (type "text") (id "guess"))))
2769
2770(define-page (main-page-path)
2771  (lambda ()
2772    (ajax "try-guess" 'guess 'change
2773          (lambda ()
2774            (let ((guess ($ 'guess as-number))
2775                  (thinking (random 10)))
2776              `(p ,(if (and guess (= guess thinking))
2777                       "You guessed it right!"
2778                       `("You guessed it wrong. I'm thinking " ,thinking ".")))))
2779          target: "verdict"
2780          arguments: '((guess . "$('#guess').val()")))
2781    `((p "Guess the number I'm thinking:")
2782      ,(prompt-guess)
2783      (div (@ (id "verdict")))))
2784  use-ajax: #t)
2785</enscript>
2786
2787To run it, execute:
2788
2789  $ awful number-guess.scm
2790
2791(considering you saved the code above in a file called
2792{{number-guess.scm}}), then access {{http://localhost:8080}}.
2793
2794
2795
2796==== Sandboxed Chicken Web REPL
2797
2798It shows how to implement a very simple web-based Chicken REPL using a
2799sandbox environment (see the
2800[[/egg/sandbox|sandbox egg]] documentation) for
2801safe evaluation.
2802
2803The idea is to have a web page with an input box. Users type the forms
2804they want to evaluate and submit them to the server. The server
2805evaluates the given forms in a sandbox environment and return the
2806results.
2807
2808Here's the commented code:
2809
2810<enscript highlight=scheme>
2811(cond-expand
2812  (chicken-4
2813    (use awful sandbox))
2814  (chicken-5
2815    (import (chicken base)
2816            (chicken condition)
2817            (chicken port))
2818    (import awful sandbox)))
2819
2820(enable-sxml #t)
2821
2822;; Here we define the REPL page.  It uses the session to store the
2823;; sandboxed environment.  By default, the `main-page-path' parameter
2824;; value is "/".
2825(define-session-page (main-page-path)
2826  (lambda ()
2827
2828    ;; Create the sandbox environment (if it does not exist yet) and
2829    ;; store it in the user session.
2830    (unless ($session 'sandbox-env)
2831      ($session-set! 'sandbox-env
2832                     (make-safe-environment
2833                      parent: default-safe-environment
2834                      mutable: #t
2835                      extendable: #t)))
2836
2837    ;; Here we set an ajax handler for the REPL expressions
2838    ;; submission.  When users change the REPL input widget (i.e., by
2839    ;; pressing ENTER), the contents of the text input field are
2840    ;; submitted and handled by the procedure given as the fourth
2841    ;; argument to `ajax'.
2842    (ajax "eval" 'repl-input 'change
2843          (lambda ()
2844
2845            ;; This binds the variable `repl-input' from the POST
2846            ;; method the the `repl-input' Scheme variable
2847            (let ((repl-input ($ 'repl-input)))
2848
2849              ;; We'd better handle exceptions when trying to
2850              ;; evaluate the expressions given by users.
2851              (handle-exceptions
2852               exn
2853               ;; If something goes wrong, we print the error message
2854               ;; and the call chain.
2855               `(pre ,(with-output-to-string
2856                        (lambda ()
2857                          (print-error-message exn)
2858                          (print-call-chain))))
2859               ;; Here we try to evaluate the given expression in the
2860               ;; sandboxed environment stored in the user session.
2861               ;; The `repl-output' page div is updated with the result.
2862               `(pre ,(safe-eval
2863                       (with-input-from-string repl-input read)
2864                       fuel: 100
2865                       allocation-limit: 100
2866                       environment: ($session 'sandbox-env))))))
2867
2868          ;; Here we pass the contents of the text input to the ajax
2869          ;; handler.  The default HTTP method used by `ajax' is POST.
2870          arguments: `((repl-input . "$('#repl-input').val()"))
2871
2872          ;; The output of the ajax handler updates the `repl-output'
2873          ;; page div.
2874          target: "repl-output")
2875
2876    ;; Here's what is displayed to users
2877    `((h1 "Sandboxed Chicken web REPL")
2878      (input (@ (type "text") (id "repl-input")))
2879      (div (@ (id "repl-output")))))
2880
2881  ;; This tells `define-session-page' to link the page to jQuery
2882  use-ajax: #t)
2883</enscript>
2884
2885To run the code above you'll need to install awful and sandbox:
2886
2887  $ chicken-install awful sandbox
2888
2889Then (considering you save the code above in a file called {{web-sandbox.scm}}), run:
2890
2891  $ awful web-sandbox.scm
2892
2893and access {{http://localhost:8080}}.
2894
2895
2896Here are some screenshots of the code above running on Firefox:
2897
2898[[image://gazette.call-cc.org/img/10/web-sandbox.png|Screenshot of the sandboxed web REPL running on Firefox]]
2899
2900If you try something nasty, the sandbox will abort the evaluation and you'll get an error message and the call chain:
2901
2902[[image://gazette.call-cc.org/img/10/web-sandbox-loop.png|Screenshot of the sandboxed web REPL running on Firefox]]
2903
2904We can also compile the web application:
2905
2906 $ csc -s web-sandbox.scm
2907 $ awful web-sandbox.so
2908
2909
2910==== Color chooser
2911
2912Here's an example provided by
2913[[/users/christian-kellermann|Christian Kellermann]] demonstrating an ajax-based color chooser:
2914
2915<enscript highlight=scheme>
2916(cond-expand
2917  (chicken-4
2918    (use awful))
2919  (chicken-5
2920    (import awful)))
2921
2922(define color-table
2923  '("f63353" "fead76" "107279" "10fabc" "1181bf" "120902" "129105"
2924    "131848" "13a04b" "1427ee" "14a8b1" "1532d4" "15bcf7" "16671a"
2925    "16c13d" "175b60" "17d583" "186fa6" "18ecc9" "1973ec"))
2926
2927(define (color-picker counter color)
2928  `(div (@ (class "color-box")
2929           (style ,(string-append "background-color: #" color)))
2930        (input (@ (type "text")
2931                  (id ,(conc "change-color-" counter))
2932                  (value ,color)))))
2933
2934(define (make-color-chooser counter c)
2935  (ajax "ajax" (conc "#change-color-" counter) 'change
2936        (lambda ()
2937          (let ((color (or ($ 'color) c))
2938                (counter ($ 'counter)))
2939            (color-picker counter color)))
2940        target: (conc "color-box-" counter)
2941        arguments: `((color . ,(conc  "$('#change-color-" counter "').val()"))
2942                     (counter . ,counter))
2943        live: #t)
2944  `(div (@ (id ,(conc "color-box-" counter)))
2945        ,(color-picker counter c)))
2946
2947(define-page (main-page-path)
2948  (lambda ()
2949    (map (let ((counter -1))
2950           (lambda (c)
2951             (set! counter (add1 counter))
2952             (make-color-chooser counter c)))
2953         color-table))
2954  use-ajax: #t)
2955</enscript>
2956
2957Here's a screenshot:
2958
2959[[image://parenteses.org/mario/img/awful/color-chooser.png|Awful color chooser]]
2960
2961To run this example (considering you save the code above in a file called {{color-chooser.scm}}):
2962
2963  $ awful color-chooser.scm
2964
2965then access {{http://localhost:8080}}.  You can change the colors by
2966editing the input boxes then pressing enter.
2967
2968
2969==== Fortune server
2970
2971Note: this example assumes CHICKEN 4.
2972
2973This example is a fortune server in awful.  It demonstrates some handy
2974awful features like database access and ajax.  You'll need the
2975[[/egg/awful-sql-de-lite|awful-sql-de-lite]]
2976egg and its dependencies (which should be automatically installed by
2977{{chicken-install}}).
2978
2979Here are instructions to install and use it:
2980
29811. Install [[/egg/awful-sql-de-lite|awful-sql-de-lite]]
2982
2983   $ chicken-install awful-sql-de-lite
2984
2985
29862. Create the fortunes database (see the code below):
2987
2988   $ csi -s create-database.scm
2989
2990
29913. Run the fortune server (see the code below):
2992
2993   $ awful fortune-server.scm
2994
2995
2996Here's the code for {{create-database.scm}} which creates and populates the fortune database:
2997
2998<enscript highlight=scheme>
2999(use sql-de-lite posix)
3000
3001(define fortunes
3002  '(("Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
3003     "Brian Kernighan")
3004    ("In order to understand recursion, one must first understand recursion.")
3005    ("If debugging is the process of removing software bugs, then programming must be the process of putting them in."
3006     "Edsger Dijkstra")
3007    ("Controlling complexity is the essence of computer programming."
3008     "Brian Kernigan")
3009    ("The function of good software is to make the complex appear to be simple."
3010     "Grady Booch")
3011    ("That's the thing about people who think they hate computers.  What they really hate is lousy programmers."
3012     "Larry Niven")
3013    ("First learn computer science and all the theory.  Next develop a programming style.  Then forget all that and just hack."
3014    "George Carrette")
3015    ("To iterate is human, to recurse divine."
3016    "L. Peter Deutsch")
3017    ("The best thing about a boolean is even if you are wrong, you are only off by a bit.")
3018    ("Optimism is an occupational hazard of programming; feedback is the treatment."
3019     "Kent Beck")
3020    ("Simplicity is prerequisite for reliability."
3021     "Edsger W. Dijkstra")
3022    ("Simplicity is the ultimate sophistication."
3023     "Leonardo da Vinci")
3024    ("The unavoidable price of reliability is simplicity."
3025     "C.A.R. Hoare")
3026    ("The ability to simplify means to eliminate the unnecessary so that the necessary may speak."
3027     "Hans Hoffmann")
3028    ("Simplicity is hard to build, easy to use, and hard to charge for. Complexity is easy to build, hard to use, and easy to charge for."
3029     "Chris Sacca")))
3030
3031(delete-file* "fortunes.db")
3032
3033(let ((db (open-database "fortunes.db")))
3034  (exec (sql db "create table fortunes(sentence text, author text)"))
3035  (for-each (lambda (fortune)
3036              (let* ((sentence (car fortune))
3037                     (author (cdr fortune))
3038                     (statement
3039                      (string-append
3040                       "insert into fortunes (sentence, author) values (?,?)")))
3041                (exec (sql db statement)
3042                      sentence
3043                      (if (null? author) "" (car author)))))
3044            fortunes)
3045  (close-database db))
3046</enscript>
3047
3048Here's the code for the fortune server:
3049
3050<enscript highlight=scheme>
3051(use awful awful-sql-de-lite)
3052
3053(enable-sxml #t)
3054(enable-db)
3055(db-credentials "fortunes.db")
3056
3057(define (random-fortune)
3058  (car ($db "select sentence, author from fortunes order by random() limit 1")))
3059
3060(define-page (main-page-path)
3061  (lambda ()
3062    (ajax "new-fortune" 'new-fortune 'click
3063          (lambda ()
3064            (let ((fortune (random-fortune)))
3065              `((sentence . ,(car fortune))
3066                (author . ,(cadr fortune)))))
3067          update-targets: #t)
3068
3069    `(div (@ (id "content"))
3070          (div (@ (id "sentence"))
3071               "Click the button below to get a new fortune")
3072          (div (@ (id "author")))
3073          (button (@ (id "new-fortune")) "New fortune")))
3074  css: "fortune.css"
3075  use-ajax: #t
3076  charset: "utf-8")
3077</enscript>
3078
3079
3080The contents of the {{fortune.css}} file are:
3081
3082<enscript highlight=css>
3083body
3084{ font-family: arial, verdana, sans-serif;
3085}
3086
3087#sentence
3088{ width: 20em;
3089  background-color: #DEE7EC;
3090  padding: 6px;
3091  min-height: 7em;
3092}
3093
3094#author
3095{ width: 20em;
3096  min-height: 2em;
3097  padding: 6px;
3098  background-color: #eee;
3099}
3100</enscript>
3101
3102Here's a screenshot:
3103
3104[[image://parenteses.org/mario/img/awful/fortune-server.png|Awful fortune server]]
3105
3106
3107==== I-wonder
3108
3109I-wonder is a simple awful example application which uses SQLite as
3110storage (with the [[/egg/sql-de-lite|sql-de-lite]] egg).
3111
3112You can find the code for that application on GitHub: [[https://github.com/mario-goulart/i-wonder|https://github.com/mario-goulart/i-wonder]]
3113
3114Here's a screenshot
3115
3116[[image://parenteses.org/mario/img/awful/i-wonder.png|I-wonder]]
3117
3118=== The name
3119
3120Awful doesn't mean anything special.  It's just awful.  But folks on freenode's #chicken (IRC) have suggested some acronym expansions:
3121
3122* A Whole Freaking Universe of Lambdas
3123* Authored Without Full Understanding of Logic
3124* Another Web Framework Understating Logic
3125* All Worthless Frameworks Unchain Laziness
3126* Armed With Flimsy Utility Lisp
3127* Awful Will Fed Up Lispers
3128* Awful Wildly Finalizes Unfinished Loops
3129* Another Widely Foolish Unknown Language
3130* Ain't Work For Unpleasant Laywers
3131* Aliens Would Find it Utterly Lame
3132* Aren't We Funny and Uncaring Lurkers
3133* Awful Will F*** Up Logic
3134* Awful Will Fart Upon Leaving
3135* Again Web Frameworks Underscore Lameness
3136* Attention While Fully Utilizing Laziness
3137* Another Webserver F***ing Up the Line
3138* Again We Forget Unclosed Lambdas
3139* All Web Features Understood Losslessly
3140* Anything With Fully Universal Lambdas
3141* Again We Fail Under Load
3142* Apocalyptic Warthogs Find Undiscovered Lands
3143* Accessible Web Framework Using Lisp
3144* Another Weird Framework Using Lisp
3145* All Waffles Fear Unicorn Landings
3146* A Working Facility Underscoring Laziness
3147* Another Webbot Flapping Under Lines
3148* Anybody Will Fake Unrealistic Loveletters
3149* Armadillos Would First Use Legs
3150* Astonishing Whales Fill Up Lakes
3151* Alternative Way to F*** Up Lisp
3152* Another Way to Find Undressed Ladies
3153* Amazing! Wonderful! Fantastic! Unbelievable! Lame.
3154* All Wonders Feel Useless Later
3155* Amazingly Wonderful Feeling, Using Lambdas
3156* Alligators Will Fear Us, Lunatics
3157* All Wussies Fear Ultimate Lambda
3158* Animals Will Find Us Letal
3159* Advanced Web Framework: Ultimate Lucubration
3160* Awful Will Feed Urban Lethargy
3161* Argument With Focus Upon Labelling
3162* Another Word Faking Unpremeditated Label
3163* Again We Find it Utterly Useless
3164* Ain't Work For Unattractive Ladies
3165* A Way For Using Lambdas
3166* Awful Way For Using Lambdas
3167* Apparently We Freaks Understand Lambdas
3168* Again We Foolishly Use Lists
3169* At Work Fools Use Lisp
3170* Again We Foolishly Use Lisp
3171* Another Wimp Fall Upon Lisp
3172* Accepting Whatever Fools Undertake Lightly
3173* Absurd Word For Unnatural Lingo
3174* Alternative Word For Useless Loser
3175* Acronym With Filled Up Letters
3176* Acronym We Find Utterly Lame
3177* Another Webserver Functioning Until Launched
3178* Applications With Familiar, Understandable Language
3179* (Awful Words Forming Useless List)
3180* All Who Force Unusual Layout
3181* Again We Fear Undescribable Lamenting
3182* Awful Will Favour Ugly Layouts
3183* Apes With Frequent Uncontrolled Lunacy
3184
3185==== Acknowledgements (IRC nicknames on freenode's #chicken):
3186
3187
3188* C-Keen
3189* DerGuteMoritz
3190* elderK
3191* elf
3192* florz
3193* merlincorey
3194* sjamaan
3195
3196=== FAQ (aka Fakely Asked Questions)
3197
3198==== How does awful bind URIs to files/directories on the filesystem and procedures?
3199
3200Explanation by example:
3201
3202When a procedure is bound to a path {{a}} (like {{(define-page "a" (lambda ...))}}) and the request is made to {{a/}}, the awful behavior is the following:
3203
3204* if the path {{a}} does not exist in the filesystem (under the {{root-path}}), the server replies with the result of the evaluation of the procedure bound to {{a}}.
3205
3206* if {{a}} is an existent file, the server replies with the file contents (or the result of processing the file, in case it is a special one like [[/egg/spiffy#web-scheme-handler|web-scheme]] or {{.ssp}} files)
3207
3208* if {{a}} is an existing directory and the directory contains one of the files in {{index-file}} (see documentation for [[/egg/spiffy|Spiffy]]), with the index file contents (or the result of processing the file, in case it is a special one like [[/egg/spiffy#web-scheme-handler|web-scheme]]'s or {{.ssp}})
3209
3210* if {{a}} is an existing directory and does not contain index files, the server replies with the result of the evaluation of the  procedure bound to {{a}}.
3211
3212=== Known bugs and limitations
3213
3214* Awful currently doesn't detect if cookies are enabled on the client side.
3215
3216* Reloading of compiled applications is not supported (i.e., you have defined a page to reload your compiled applications). See [[http://bugs.call-cc.org/ticket/442|ticket #442]].
3217
3218* When {{define-page}}'s {{no-template}} is not false,
3219{{add-javascript}} and ajax-related features for {{define-page}}
3220won't be effective for the page in question.
3221
3222* If you encounter bugs, please report them to the author.
3223
3224=== License
3225
3226  Copyright (c) 2010-2018, Mario Domenech Goulart
3227  All rights reserved.
3228 
3229  Redistribution and use in source and binary forms, with or without
3230  modification, are permitted provided that the following conditions
3231  are met:
3232  1. Redistributions of source code must retain the above copyright
3233     notice, this list of conditions and the following disclaimer.
3234  2. Redistributions in binary form must reproduce the above copyright
3235     notice, this list of conditions and the following disclaimer in the
3236     documentation and/or other materials provided with the distribution.
3237  3. The name of the authors may not be used to endorse or promote products
3238     derived from this software without specific prior written permission.
3239 
3240  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
3241  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3242  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3243  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
3244  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3245  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3246  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3247  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3248  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3249  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
3250  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3251
3252=== Version history
3253
3254===== version 1.0.0
3255
3256* CHICKEN 5 support
3257* Drop support for page handlers that produce strings ("string mode").  Now only SXML is supported.
3258* {{enable-sxml}} has been deprecated.  It is still available, but doesn't do anything.
3259* Drop dependency on the following eggs: regex, html-tags, html-utils
3260* The following deprecated procedures have been removed: {{++}}, {{concat}}
3261* New procedure: {{html-page}}
3262
3263
3264===== version 0.42.0
3265
3266* Use SPIFFY_TEST_PORT environment variable's value (if provided) for tests
3267
3268* Make {{awful-start}} properly honor the {{dev-mode?}} keyword parameter. Before this change, {{development-mode-actions}} would only be called from {{load-apps}}.  So, if an application uses {{awful-start}} with {{dev-mode?}} set to {{#t}}, but doesn't call {{load-apps}}, {{development-mode-actions}} would not be called.  While at it, call {{development-mode-actions}} ''before'' evaluating the thunk for {{awful-start}}, so that the evaluated code can override the settings made by {{development-mode-actions}}.
3269
3270* Bug fix for {{form}} in SXML mode. Thanks to Thomas Hintz for spotting that issue.
3271
3272* {{debug-file}}: its value can now also be an output-port. {{debug}} and {{debug-pp}} will properly handle the {{debug-file}} value types: filenames (strings) or output port objects.
3273
3274* Add {{strict}} keyword parameter for define-page and ajax & friends
3275
3276For convenience, awful sloppily considered requests for files and
3277directories to be equivalent.  For example, if a page was defined with
3278a {{"/foo"}} matcher, a request for {{"/foo/"}} would be handled by
3279{{"/foo"}}'s handler.
3280
3281That's not always desired.  For example, consider this case:
3282
3283  (define-page (irregex "/[^/]*") identity)
3284
3285We want to specify that, e.g., requests for {{/foo}} should be
3286handled, but requests for {{/foo/}} should ''not'' be handled.  However,
3287since awful tries to find a handler by stripping the trailing slash, a
3288request for {{/foo/}} would actually be handled by the handler for
3289{{(irregex "/[^/]*")}}, even if the regex specified that paths with a
3290trailing slash should not match.
3291
3292To work around that inconsistency, a new keyword parameter has been
3293added to {{define-page}}, {{ajax}}, {{periodical-ajax}} and
3294{{ajax-link}}: {{strict}} (default: {{#f}}, for backward
3295compatibility).  If the {{strict}} keyword parameter is truthy, awful
3296will not try to find a handler for the requested path by removing the
3297trailing slash.
3298
3299With this change, the format of the resources table has changed too.
3300Now the value part of hash table items is a pair whose car is the
3301resource handler and the cdr is a boolean indicating whether the
3302resource is "strict" or not.
3303
3304
3305===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=32298|version 0.41.0]]
3306
3307* The deprecated procedure {{sql-quote}} has been removed
3308
3309* Set the default value for {{$db}}'s {{default}} keyword param as {{'()}}
3310
3311To be consistent with the db-support eggs for awful.
3312
3313'''WARNING''': this change may break your code!  In case of an empty
3314result set from a query, {{$db}} will now return {{'()}} instead of
3315{{#f}}.
3316
3317This change can be specially harmful in case you have something like
3318
3319<enscript highlight=scheme>
3320         (or ($db "some query") "something")
3321</enscript>
3322
3323In this example, if the query returns an empty result set, that
3324expression would produce:
3325
3326* in older awful versions: {{"something"}}
3327* in awful versions with this change: {{'()}}
3328
3329To work around the incompatible behaviors, you can:
3330
3331* require awful 0.41.0 in you .meta file
3332* always provide a value for {{$db}}'s {{default}} keyword parameter
3333
3334
3335===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=30483|version 0.40.0]]
3336* SSQL support for {{$db}} and {{$db-row-obj}}
3337* Full support for static pages generation (via [[/egg/awful-static-pages|awful-static-pages]])
3338* {{--privileged-code}} now accepts multiple files (comma-separated)
3339* Bug fixes in web-repl when in SXML mode
3340* The default value for {{use-fancy-web-repl?}} is now {{#t}} in {{awful-start}} (to match the command line application's default behavior)
3341* jQuery updated to 1.11.0
3342
3343===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=30336|version 0.39.2]]
3344* jQuery's {{on}} method support for {{ajax}} & friends
3345* {{use-sxml}} keyword parameter for {{define-page}} and {{ajax}} & friends take precedence over {{enable-sxml}}. {{use-sxml}} can now be used to disable SXML mode for certain pages and {{ajax}} handlers when bound to {{#f}} (thanks to Thomas Hintz for reporting that issue)
3346* Fix redirection to login page when in SXML mode (regression introduced by 03e4e6b9ca2378928fa35c5b8b68738561010aa2 in 0.39.1). Thanks to Thomas Hintz for reporting that and suggesting removing html-tags code
3347
3348===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=29489|version 0.39.1]]
3349* Update jQuery to version 1.10.2
3350* Bug fix: {{page-path}} should return {{(app-root-path)}} when given {{"/"}}
3351* Bug fix: check to make sure redirect-to-login-page always generates HTML (patch by Hugo Arregui)
3352
3353===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=28751|version 0.39]]
3354
3355* The default methods for {{define-page}} are now HEAD and GET (thanks to Thomas Hintz)
3356* Bug fix for {{link}} in SXML mode
3357* Add {{define-app}} macro
3358* Add {{literal-script/style?}} parameter (suggested by John J. Foerch)
3359* Add {{add-css}} procedure (suggested by John J. Foerch)
3360
3361
3362===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=28237|version 0.38.2]]
3363
3364* Fix bug related to path matchers as procedures and sessions which caused errors, for example, on redirections from pages defined with path matchers as procedures to the login page
3365
3366
3367===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27797|version 0.38.1]]
3368
3369* Fix bug in handler for {{/reload}} when in development mode and in SXML mode
3370* Versions now have a second dot for bugfix releases
3371
3372
3373===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27701|version 0.38]]
3374
3375* Fix bug in {{define-page}} when page handlers return procedures
3376
3377
3378===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27693|version 0.37]]
3379
3380* Fix {{page-exception-message}} when in development mode and using SXML (thanks to sECuRE for catching that)
3381
3382
3383===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27510|version 0.36]]
3384
3385* SXML support.  The use of SXML mode (i.e., {{(enable-sxml #t)}} is highly encouraged.  All the documentation examples show SXML code.  Page handlers that yield strings are deprecated and support for them will be removed in future versions.
3386* {{++}} and {{concat}} have been deprecated (they are still available, but will be removed in future versions).
3387* jQuery updated to version 1.8.2
3388
3389
3390===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=26831|version 0.35]]
3391
3392* Added {{awful-resources-table}}
3393* Added {{set-page-title!}} (thanks to John J. Foerch for suggesting that)
3394* {{define-page}}'s first argument (the path matcher) can now be a procedure (thanks to John J. Foerch for suggesting that)
3395* The return value of the second argument to {{define-page}} can now be a procedure
3396* {{add-request-handler-hook!}} overwrites hooks with the same name instead of adding multiple copies
3397* {{define-page}}'s {{use-ajax}} keyword parameter can also be bound to a string indicating the path to the ajax library
3398* Code moved to GitHub
3399
3400
3401===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25890|version 0.34]]
3402* Don't check {{current-effective-user-id}} on windows, since it is not available on that platform.  Reported by Karl_H on #chicken.
3403* Use {{<label>}} instead of {{<span>}} for login form labels (patch by Arthur Maciel).  Warning: this change may break your login form layout if you rely on the specific {{<span>}} tags for form labels.
3404
3405
3406===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25689|version 0.33]]
3407* jQuery updated to version 1.7.1
3408* Added {{session-cookie-setter}} (thanks to Thomas Hintz)
3409* Added {{event}} argument to anonymous JavaScript function given as argument to {{bind}}/{{live}} ({{ajax}} and friends).  Patch by Thomas Hintz.
3410* The {{method}} keyword parameter for {{define-page}} and {{ajax}} & friends can be bound to a list of methods.  Methods are now case insensitive.
3411
3412===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25073|version 0.32]]
3413* Added {{method}} keyword parameter for {{define-page}}.  Now the page router takes into account the HTTP method, so it is possible to have two different pages using the same path but different methods.
3414* Added {{error-handler}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}} (suggested by Thomas Hintz)
3415* {{ajax}} and friends send {{Content-Type: application/json}} when {{update-targets}} is non-#f
3416* {{ajax}} bugfix: only opens db connection and refresh session when the page access is allowed
3417* The default value for {{awful-backlog}} has been set to 100
3418* Updated jQuery from version 1.5.2 to 1.6.3
3419* Dropped {{-lambda-lift}} build option
3420* Added the {{reload-apps}} procedure. {{load-apps}} no longer resets the resources table
3421* {{awful-start}} requires a thunk as argument. With this, awful can be embedded into standalone applications
3422
3423
3424===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=23515|version 0.31]]
3425* Added a tiny wrapper around [[/egg/spiffy-request-vars|spiffy-request-vars]], adding the {{with-request-variables}} macro and exporting {{spiffy-request-vars}}'s converters.
3426* Updated jQuery from version 1.5.1 to 1.5.2.
3427* Better support for multiple applications under the same virtual host ({{add-request-handler-hook!}} and {{remove-request-handler-hook!}})
3428* {{$db}} checks if database access is enabled via {{(enable-db)}} and throws an error if it is not.
3429* Fixed critical bug regarding to parameters and thread reuse by Spiffy
3430* Fixed {{redirect-to}} but introduced in version 0.29
3431
3432===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=23075|version 0.30]]
3433* The {{(ajax-library)}} is always linked before any other scripts and JavaScript code in the headers (i.e., when {{(javascript-position)}} is {{top}}).
3434* Ajax-related procedures simplifications and bugfix in the session awareness code when called from {{define-session-page}}.
3435
3436===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=22907|version 0.29]]
3437* Updated jQuery from version 1.5.0 to 1.5.1.
3438* {{ajax}} and {{periodical-ajax}} bugfix (for situations when they are used simultaneously, or {{periodical-ajax}} and {{add-javascript}}).
3439* The default URI for {{ajax-library}} is now protocol-relative (thanks to Peter Bex).
3440* Added the {{javascript-position}} parameter.
3441
3442===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=22639|version 0.28]]
3443* Updated jQuery from version 1.4.3 to 1.5.0.
3444* {{ajax}} and friends ({{periodical-ajax}}, {{ajax-link}}) are now session-aware when called from {{define-session-page}} (i.e., you don't need to explicitly pass the session identifier).
3445* Added the {{cache}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}}.
3446* The HTTP request variables are now parsed and made available on demand, when {{$}} is called for the first time for each request (thanks to David Krentzlin).
3447* Applications are no longer loaded with administrator privileges when awful is run by administrator and configured to switch to a non privileged user. For code which needs administrator privileges (like binding to low ports, IP addresses, user/group settings, etc.), there's a new command line option for the awful application server: {{--privileged-code}}.  '''Warning''': if you rely on your configuration performing actions with administrator privileges, this change may affect your code.
3448* {{define-session-page}} bug fix (it was not properly obtaining the session identifier).
3449
3450
3451===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=20689|version 0.27]]
3452* Require the {{regex}} egg, for chickens >= 4.6.2
3453
3454===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=19844|version 0.26]]
3455* {{define-page}} allows page redefinitions
3456* Added the {{undefine-page}} procedure
3457* Fancy web REPL (enabled by default).  The awful application server now accepts the {{--disable-web-repl-fancy-editor}} command line option to disable the web REPL fancy editor.
3458* Added the following parameters, related to the fancy web REPL: {{enable-web-repl-fancy-editor}} and {{web-repl-fancy-editor-base-uri}}.
3459* Bug fix for the development mode: requests to the {{/reload}} path killed {{/web-repl}} and {{/session-inspector}}
3460
3461===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=19496|version 0.25]]
3462* The awful application server can now be used with the {{--development-mode}} command line option, which enables the web REPL, the session inspector (when {{enable-session}} is #t) for the localhost and on-browser error messages and backtraces.  When running in development mode, the {{/reload}} path is defined to reload awful apps.
3463* The awful application server now supports the {{--ip-address}} and {{--port}} command line options.
3464* {{use-ajax}} keyword parameter for {{define-page}} (for when {{enable-ajax}} is {{#f}} and you need ajax for some specific pages only)
3465* Added {{awful-response-headers}} and {{development-mode?}} parameters
3466
3467===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18903|version 0.24]]
3468* initial support for storing session identifiers in cookies.  Added the {{enable-session-cookie}} and {{session-cookie-name}} parameters.  By default, cookies-sessions are enabled (relevant only when using sessions, of course). '''Warning''': if your code relies on the availability of session identifiers in the query string or in the request body for whatever reason, it will break.
3469* initial support for HTTP redirection via {{redirect-to}}.
3470* web-repl and session-inspector beautification
3471* web-repl and session inspector provide a {{headers}} keyword parameter
3472* fixes for {{define-page}} regarding to regex-based paths
3473* {{ajax}} always prioritizes the {{success}} keyword parameter value (when it's given) to generate code for jQuery's {{success}} attribute, even when {{target}} and {{update-targets}} are given
3474* awful (the application) handles the {{-v}} and {{--version}} command line options
3475
3476===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18559|version 0.23]]
3477* added the {{update-targets}} keyword parameter for {{ajax}}, {{periodical-ajax}} and {{ajax-link}} procedures (multiple targets update support)
3478* added the {{debug-resources}} parameter for debugging the resources table
3479* the {{js}} keyword parameter for {{ajax}}, {{periodical-ajax}} and {{ajax-link}} has been renamed to {{success}} (to match jQuery's API naming for Ajax). '''Warning''': if your code uses the {{js}} keyword parameter for {{ajax}}, {{periodical-ajax}} or {{ajax-link}}, this change will break your code.
3480* the JavaScript variable bound to the response data on successful ajax request has been renamed to {{response}} (it was {{h}} before). The same warning for the {{js}}->{{success}} renaming is valid for this change, since it is directly related to {{js}} (now {{success}}).
3481* the default value for {{main-page-path}} is now {{"/"}} (it was {{"/main"}} before).  There's no more main page redirection.  '''Warning''': if your code relies on hardcoded {{"/main"}} paths (instead of using {{(main-page-path)}}) or if you rely on the main page automatic redirection, this change will break your code.
3482* {{ajax}} bugfix regarding to session identifiers (could cause "Invalid session ID" errors in some cases, specially with {{define-session-page}}).
3483* better handling of URI paths regarding to paths as directories (see FAQ's ''How does awful bind URIs to files/directories on the filesystem and procedures?'')
3484
3485===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18328|version 0.22]]
3486* bug fix: fixed unintended shadowing of {{js}} in ajax
3487* added the {{prelude}} keyword parameter for {{ajax}}, {{periodical-ajax}} and {{ajax-link}}
3488* {{$db}} supports the {{values}} keyword parameter (patch by Stephen Eilert)
3489* awful (the application) can now be invoked without arguments
3490* awful (the application) handles {{-h}} and {{--help}}
3491* dropped [[/eggref/4/jsmin|jsmin]] requirement
3492
3493===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18149|version 0.21]]
3494* ajax and main page redirection issues fixes
3495
3496===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18051|version 0.20]]
3497* {{page-access-control}} controls access to pages even when no session is in use
3498* '''Warning''': the following parameters have been removed: {{enable-reload}}, {{reload-path}} and {{reload-message}}.  Now the way to define reloaders is via {{define-page}}.
3499* new parameter: {{awful-apps}} (a list of awful applications as passed to the awful server)
3500
3501===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18040|version 0.19]]
3502* bug fix for {{(reload-path)}} handler
3503
3504===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18030|version 0.18]]
3505* support for regex-based page paths (see {{define-page}})
3506* {{define-page}} checks whether the second arg is a procedure.
3507* use {{-O3 -lambda-lift}} instead of {{-O2}} for compilation
3508* {{main-page-path}} redirection made with code stolen from [[/egg/spiffy|spiffy]]'s {{send-response}}
3509
3510===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17510|version 0.17]]
3511* .meta bug fix.  postgresql is not required as a dependency (thanks to Stephen Pedrosa Eilert for pointing this issue).
3512
3513===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17393|version 0.16]]
3514* added {{define-session-page}}
3515* bug fix for {{link}}
3516
3517===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17383|version 0.15]]
3518* jQuery updated to 1.4.2 ({{ajax-library}}).
3519
3520===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17350|version 0.14]]
3521* {{link}}'s {{args}} keyword parameter renamed to {{arguments}} (the same as {{ajax}}'s).
3522
3523===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17346|version 0.13]]
3524* Session-aware {{link}} and {{form}} procedures.  Bug fix for {{ajax-link}} (was not passing the {{class}} keyword argument to <a>).
3525
3526===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17278|version 0.12]]
3527* Containers for user and password fields ({{login-form}})
3528
3529===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17275|version 0.11]]
3530* awful sets Spiffy's {{root-path}} to {{(current-directory)}}
3531
3532===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17186|version 0.10]]
3533* Multiple database support. Currently PostgreSQL (via [[/egg/postgresql|postgresql]] egg) and SQLite3 (via [[/egg/sqlite3|sqlite3]] and [[/egg/sql-de-lite|sql-de-lite]] eggs) are supported.  See [[/egg/awful-postgresql|awful-postgresql]], [[/egg/sqlite3|sqlite3]] and [[/egg/sql-de-lite|sql-de-lite]] eggs.
3534* Removed requirement for postgresql
3535* {{enable-db}} is now a procedure (not a parameter as before) and accepts no arguments
3536
3537===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17172|version 0.9]]
3538* {{login-form}} gets the {{user}} refilled when the session or password is not valid.  This feature may be disabled by setting the {{refill-user}} keyword parameter for {{login-form}} to {{#f}} (default is {{#t}}).  Thanks to Arthur Maciel for suggesting this feature.
3539
3540===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17149|version 0.8]]
3541* jQuery updated to 1.4.1 ({{ajax-library}}).
3542* support for jQuery's {{live}} method ({{live}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}}).  See [[http://api.jquery.com/live/]]
3543* bug fixes: {{periodical-ajax}} and {{ajax-link}} propagate {{vhost-root-path}} to {{ajax}}
3544* added {{awful-start}} and dropped spiffy requirement for awful (the server)
3545* dropped requirement for miscmacros
3546* added more ajax tests
3547
3548===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17139|version 0.7]]
3549* {{ajax-link}} accepts all {{<a>}}'s keyword arguments
3550
3551===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17134|version 0.6]]
3552* Explicitly depends on [[/egg/http-session|http-session]] 2.0
3553
3554===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17130|version 0.5]]
3555* Reload handler register the reload path after reloading.
3556
3557===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17127|version 0.4]]
3558* {{disable-reload?}} renamed to {{enable-reload}}.  {{enable-reload}} is {{#f}} by default.
3559
3560===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17122|version 0.3]]
3561* {{awful}} (the server) allows applications to use Chicken syntax ({{use}}, {{include}}, etc.)
3562
3563===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17120|version 0.2]]
3564* Added JavaScript compression support
3565
3566===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17109|version 0.1]]
3567* Initial release
3568
Note: See TracBrowser for help on using the repository browser.