source: project/wiki/eggref/4/awful @ 33741

Last change on this file since 33741 was 33741, checked in by mario, 3 years ago

awful (wiki): update doc with changes from git

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