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

Last change on this file since 32309 was 32309, checked in by mario, 4 years ago

awful (wiki): update documentation for version 0.42.0

  • Property svnwiki:tags set to web awful
  • Property svnwiki:title set to Awful
File size: 119.5 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
1555
1556===== {{$db-row-obj}}
1557<procedure>($db-row-obj q)</procedure>
1558
1559Execute the given query {{q}} on the database and return an
1560one-argument procedure which takes as argument the name of the
1561database field to get the value.
1562
1563Example:
1564
1565<enscript highlight=scheme>
1566(let ((& ($db-row-obj "select full_name, phone from users where user_id=1")))
1567  (<p> "Full name: " (& 'full_name))
1568  (<p> "Phone: " (& 'phone)))
1569</enscript>
1570
1571''Warning'': currently {{$db-row-obj}} is only implemented for
1572PostgreSQL databases.
1573
1574If you use the [[/egg/awful-ssql|awful-ssql]] egg, you can give
1575{{$db}} the query as a SSQL expression.  See the documentation for
1576[[/egg/awful-ssql|awful-ssql]] for more details.  Support for SSQL has
1577been introduced in awful version 0.40.0.
1578
1579
1580==== Pages
1581
1582===== {{define-page}}
1583<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 strict)</procedure>
1584
1585Define an awful page.
1586
1587{{path-matcher}} matches requested paths.  It can be represented by three types:
1588; string: a literal path. When the path matcher is a string, the handler procedure must be a thunk.
1589; 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.
1590; 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.
1591
1592
1593{{handler}} should return either a string or a no-argument procedure.
1594If it returns a string, it will be given as argument to
1595{{(page-template)}}, unless {{no-template}} is not false. If
1596{{handler}} returns a procedure (feature introduced in awful 0.35),
1597awful won't do anything besides evaluating the returned procedure.  It
1598can be useful, for example, to serve static files out of the web
1599server document directory (see the examples in this section).
1600
1601{{use-sxml}} (boolean): specifies whether awful should assume that the
1602handler produces SXML code or strings.  In case the handler produces
1603SXML code, the parameter {{sxml->html}} yields the procedure used to
1604generate HTML out of SXML.
1605
1606{{method}} (a symbol or a list) indicates the HTTP method to be used
1607(e.g., {{GET}}, {{POST}}, {{PUT}}).  {{method}} can also be a list of
1608methods.  In this case, awful will define a page for each method of
1609the list.  Methods are case-insensitive.  Pages that use different
1610methods can use the same path.  The default value is {{(GET HEAD)}}
1611(prior to version 0.39, the default value was just {{GET}}).
1612
1613The {{css}}, {{title}}, {{doctype}}, {{headers}} and {{charset}}
1614keyword parameters have the same meaning as {{html-page}} (from the
1615[[/egg/html-utils|html-utils]] egg).
1616
1617If {{no-ajax}} is {{#t}}, it means that the page won't use ajax, even
1618if the {{enable-ajax}} parameter is {{#t}}.
1619
1620If {{use-ajax}} is {{#t}}, it means that the page will be linked to
1621the ajax library, even if the {{enable-ajax}} parameter is {{#f}}.
1622
1623If {{no-template}} is {{#t}}, it means that no page template (see the
1624{{page-template}} parameter) should be used.
1625
1626If {{no-session}} is {{#t}}, it means that the page should not use session.
1627
1628If {{no-db}} is {{#t}}, it means that the page should not use the
1629database, even when database usage is activated by {{enable-db}} and
1630{{db-credentials}} is not {{#f}}.
1631
1632If {{no-javascript-compression}} is {{#t}} the JavaScript code for the
1633page is not compressed, even when {{enable-javascript-compression}} is
1634not {{#f}}.
1635
1636If {{strict}} is truthy, awful will only match the requested path if
1637it strictly matches the defined matchers.  For convenience, awful
1638sloppily considered requests for files and directories to be
1639equivalent.  For example, if a page was defined with a {{"/foo"}}
1640matcher, a request for {{"/foo/"}} would be handled by {{"/foo"}}'s
1641handler.  That's not always desired.  For example, consider this case:
1642
1643  (define-page (irregex "/[^/]*") identity)
1644
1645We want to specify that, e.g., requests for {{/foo}} should be
1646handled, but requests for {{/foo/}} should ''not'' be handled.  However,
1647since awful tries to find a handler by stripping the trailing slash, a
1648request for {{/foo/}} would actually be handled by the handler for
1649{{(irregex "/[^/]*")}}, even if the regex specified that paths with a
1650trailing slash should not match.
1651
1652
1653Examples:
1654
1655<enscript highlight=scheme>
1656(use awful
1657     srfi-1  ;; for filter-map
1658     regex   ;; for regexp
1659     spiffy) ;; for send-static-file
1660
1661(enable-sxml #t)
1662
1663;;
1664;; Path matcher as a string
1665;;
1666
1667;; http://host:port/foo => "bar"
1668(define-page "/foo"
1669  (lambda ()
1670    "bar"))
1671
1672
1673;;
1674;; Path matcher as a regular expression
1675;;
1676
1677;; http://host:port/add/1/2/3 => 6
1678(define-page (regexp "/add/.*")
1679  (lambda (path)
1680    (let ((numbers (filter-map string->number (string-split path "/"))))
1681      `(,(apply + numbers)))))
1682
1683
1684;;
1685;; Path matchers as procedures
1686;;
1687
1688(define (ticket-id path)
1689  (and (string-prefix? "/ticket/" path)
1690       (and-let* ((tokens (string-split path "/"))
1691                  (_ (not (null? (cdr tokens))))
1692                  (id (string->number (cadr tokens))))
1693         (and id (list id)))))
1694
1695
1696(define (ticket-reporter+severity path)
1697  (and (string-prefix? "/ticket/" path)
1698       (and-let* ((tokens (string-split path "/"))
1699                  (_ (> (length tokens) 2)))
1700         (list (cadr tokens)
1701               (caddr tokens)))))
1702
1703;; http://host:port/ticket/4
1704(define-page ticket-reporter+severity
1705  (lambda (reporter severity)
1706    `(,(sprintf "Reporter=~a, severity=~a"
1707                reporter
1708                severity))))
1709
1710;; http://host:port/ticket/4/5
1711(define-page ticket-id
1712  (lambda (id)
1713    `("This is ticket " ,id)))
1714
1715
1716;;
1717;; Page handler returning a procedure
1718;;
1719
1720;; Serving a static file out of the web server documents directory
1721(define-page "/my-dot-emacs"
1722  (lambda ()
1723    (lambda ()
1724      (parameterize ((root-path (get-environment-variable "HOME")))
1725        (send-static-file ".emacs"))))
1726  no-template: #t)
1727</enscript>
1728
1729
1730===== {{define-session-page}}
1731<procedure>(define-session-page path-matcher handlerr . rest)</procedure>
1732
1733Define a session-aware page.  When the page is accessed and a
1734corresponding session does not exist, it is created.  If the session
1735already exists and is not valid, it is recreated.  If the session
1736already exists and is valid, then it is refreshed.
1737
1738The {{rest}} parameters are the same as for {{define-page}}.
1739
1740Here's an example (the [[http://www.paulgraham.com/arcchallenge.html|arc challenge]]):
1741
1742<enscript highlight=scheme>
1743(use awful)
1744
1745(enable-sxml #t)
1746
1747(define-session-page "said"
1748  (lambda ()
1749    (with-request-variables (said)
1750      (cond (said
1751             ($session-set! 'said said)
1752             `(,(link "said" "click here")))
1753            (($session 'said)
1754             => (lambda (said)
1755                  `("You said: " ,said)))
1756            (else `(,(form '((input (@ (type "text") (name "said")))
1757                             (input (@ (type "submit"))))
1758                           action: "said"
1759                           method: 'post))))))
1760  method: '(GET POST))
1761</enscript>
1762
1763
1764===== {{undefine-page}}
1765<procedure>(undefine-page path #!optional vhost-root-path)</procedure>
1766
1767Undefine a page whose path is {{path}} (a string or a regular
1768expression object).
1769
1770The optional parameter {{vhost-root-path}} is the path of virtual host
1771where the page is to be undefined.  If omitted, {{(root-path)}} is
1772used.
1773
1774
1775
1776===== {{set-page-title!}}
1777<procedure>(set-page-title! title)</procedure>
1778
1779Set the title for the requested page.  This procedure is useful to set
1780the page title dynamically from the page handler (instead of
1781statically, via {{define-page}}'s {{title}} keyword parameter).
1782
1783This procedure has been introduced in awful 0.35.
1784
1785Example:
1786
1787<enscript highlight=scheme>
1788(use awful)
1789
1790(define-page (main-page-path)
1791  (lambda ()
1792    (set-page-title! "a title")
1793    "Hi!"))
1794</enscript>
1795
1796
1797
1798==== Ajax
1799
1800===== {{ajax}}
1801<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>
1802
1803Generate JavaScript code to be added to the page defined by
1804{{define-page}}.  Return the generated JavaScript code (which usually
1805is not useful, so should be discarded).
1806
1807{{path}} is the URL path (a string) of the server side handler. This
1808path is placed under the {{(app-root-path)/(ajax-namespace)}} path.
1809So, if your {{app-root-path}} is {{"my-app"}}, your {{ajax-namespace}}
1810is {{"ajax"}} and you use {{"do-something"}} as the first argument to
1811{{ajax}}, the URL for the server side handler would be
1812{{"/my-app/ajax/do-something"}}.
1813
1814{{selector}} is the selector for the DOM element to be observed.  If
1815it is a quoted symbol, awful generates a jQuery selector by DOM id
1816(e.g., {{'my-selector}} generates {{"#my-selector"}}).  If it is a
1817string, awful uses it as-is to generate the jQuery selector (e.g.,
1818{{"input[name^=omg]"}} generates {{"input[name^=omg]"}}).
1819
1820{{event}} (a quoted symbol or a list) is the event(s) to be
1821observed. If it is a quoted symbol (e.g., {{'click}}), only this event
1822will be bound.  If {{event}} is a list of events, all the events from
1823the list will be bound.
1824
1825{{proc}} is a no-argument procedure to be executed on the server side.
1826
1827The {{target}} keyword parameter is the id of the DOM element to be
1828affected by the result of {{proc}}.
1829
1830The {{method}} (a quoted symbol, usually {{'GET}} or {{'POST}})
1831keyword parameter is the HTTP method to be used by the ajax request.
1832
1833The {{arguments}} keyword parameter is an alist mapping request
1834variables (symbols) to their values (strings).  {{ajax}} uses these
1835arguments to assembly the query string or the request body to send to
1836the server when performing the ajax request.
1837
1838If {{use-sxml}} is {{#t}}, it specifies that the ajax handler produces
1839SXML code instead of strings.
1840
1841
1842Example:
1843
1844<enscript highlight=scheme>
1845arguments: '((var1 . "$('#var1').val()")
1846             (var2 . "$('#var2').val()"))
1847</enscript>
1848
1849If the {{no-session}} keyword parameter is {{#t}}, it means that no
1850session should be considered ({{ajax}} implicit sends the session
1851identifier when {{no-session}} is {{#f}}).
1852
1853If the {{no-db}} keyword parameter is {{#t}}, it means that the should
1854be no attempt to connect the database, even when database usage is
1855activated by {{enable-db}} and {{db-credentials}} is not {{#f}}.
1856
1857The {{vhost-root-path}} keyword parameter (a string) is the vhost root
1858path.  It is useful for explicitly separate pages defined using the
1859same path (see {{define-page}}) but for different vhosts.
1860
1861The {{on}} keyword parameter (boolean) indicates whether ajax should
1862use jQuery's {{on}} method (see [[http://api.jquery.com/on/]]).  If
1863{{on}} gets bound to {{#t}}, awful will generate code to start
1864delegating events from the {{document}} DOM element.  If {{on}} gets
1865bound to a symbol, awful will generate code to start delegating events
1866from DOM element whose id is the given symbol.  If {{on}} gets bound
1867to a string, awful will generate code to start delegating events from
1868DOM element which matches the given string representing a
1869selector. The {{on}} keyword parameter was introduced in awful 0.39.2.
1870
1871The {{live}} keyword parameter (boolean) indicates whether ajax should
1872use jQuery's {{live}} method (see
1873[[http://api.jquery.com/live/]]). Note that the {{live}} method was
1874deprecated in jQuery 1.7 and removed in version 1.9.  If you are using
1875a more recent version of jQuery, see the {{on}} keyword parameter for
1876{{ajax}} (introduced in awful 0.39.2).
1877
1878The {{prelude}} keyword parameter (string) is an arbitrary piece of
1879JavaScript code to be placed right before the ajax request.
1880
1881The {{update-targets}} keyword parameter a boolean indicating whether
1882multiple targets should be updated upon ajax response.  When
1883{{update-targets}} is used, the procedure {{proc}} used as argument to
1884{{ajax}} should yield an alist as result.  The alist maps DOM elements
1885identifiers to their corresponding values.
1886
1887Here's an example:
1888
1889<enscript highlight=scheme>
1890(use awful)
1891
1892(enable-sxml #t)
1893
1894(define-page (main-page-path)
1895  (lambda ()
1896
1897    (ajax "foo" 'foo 'click
1898          (lambda ()
1899            '((a . 1) (b . 2) (c . 3)))
1900          update-targets: #t)
1901
1902    `(,(link "#" "Click me" id: "foo")
1903      (div (@ (id "a")))
1904      (div (@ (id "b")))
1905      (div (@ (id "c")))))
1906  use-ajax: #t)
1907</enscript>
1908
1909The {{success}} keyword parameter (string) can be any arbitrary
1910JavaScript code to be executed on the successful ajax request.  The
1911JavaScript code can assume that a variable {{response}} is bound and
1912contains the request resulting data.  Here's an example:
1913
1914<enscript highlight=scheme>
1915(use awful)
1916
1917(enable-sxml #t)
1918
1919(define-page (main-page-path)
1920  (lambda ()
1921
1922    (ajax "foo" 'foo "click"
1923          (lambda ()
1924            "hey")
1925          success: "$('#bar').html(response + ' you!')")
1926
1927    `(,(link "#" "Click me" id: "foo")
1928      (div (@ (id "bar")))))
1929  use-ajax: #t)
1930</enscript>
1931
1932The {{cache}} keyword parameter (boolean), if set to {{#f}}, it will
1933force requested pages not to be cached by the browser.  The default
1934value is not set, leaving it to be set by jQuery. See
1935[[http://api.jquery.com/jQuery.ajax/|jQuery's documentation]] for
1936further details.
1937
1938The {{error-handler}} keyword parameter expects a JavaScript callback
1939to be used as the error handler for the Ajax request.  See the
1940{{error}} attribute for the {{settings}} object given as argument to
1941jQuery.ajax
1942([[http://api.jquery.com/jQuery.ajax/|http://api.jquery.com/jQuery.ajax/]]).
1943
1944The {{ajax}} procedure is session, HTTP request and database -aware.
1945
1946
1947===== {{periodical-ajax}}
1948<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>
1949
1950Periodically execute {{proc}} on the server side, using
1951{{(app-root-path)/(ajax-namespace)/path}} as the URL path for the
1952server side handler.
1953
1954{{interval}} (a number) is the interval between consecutive executions
1955of {{proc}}, in milliseconds.
1956
1957The meaning of the keyword parameters is the same as for {{ajax}}'s.
1958
1959
1960===== {{ajax-link}}
1961<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>
1962
1963A shortcut to
1964
1965<enscript highlight=scheme>
1966(begin
1967  (ajax path id 'click proc ...)
1968  (<a> href: "#" [...other <a> keyword parameters...] id: id text))
1969</enscript>
1970
1971The meaning of the {{target}}, {{action}}, {{method}}, {{arguments}},
1972{{success}}, {{no-session}}, {{no-db}}, {{event}},
1973{{vhost-root-path}}, {{update-targets}} {{live}} and {{on}} keyword
1974parameters is the same as for {{ajax}}'s.
1975
1976The meaning of the {{class}}, {{hreflang}}, {{type}}, {{rel}},
1977{{rev}}, {{charset}}, {{coords}}, {{shape}}, {{accesskey}},
1978{{tabindex}} and {{a-target}} are the same as for
1979[[/egg/html-tags|html-tags]]' {{<a>}} procedure (except that
1980{{a-target}} is {{<a>}}'s {{target}}, since {{ajax}} uses the
1981{{target}} keyword parameter).
1982
1983The {{event}} keyword parameter syntax is the same for {{ajax}}'s
1984{{event}} mandatory parameter.
1985
1986
1987==== Redirection
1988
1989===== {{redirect-to}}
1990<procedure>(redirect-to uri)</procedure>
1991
1992Perform an HTTP redirection (code 302) to the given {{uri}} (either a
1993string or a [[/eggref/4/uri-common|uri-common]] URI object).  To be
1994used from {{define-page}} handler.  Example:
1995
1996<enscript highlight=scheme>
1997(use awful)
1998
1999;; / -> /foo
2000(define-page "/"
2001  (lambda ()
2002    (redirect-to "/foo")))
2003
2004(define-page "/foo"
2005  (lambda ()
2006    "foo"))
2007</enscript>
2008
2009The example above shows a redirection from {{/}} to {{/foo}}.
2010Redirections can also be performed when the origin path is a regular
2011expression:
2012
2013<enscript highlight=scheme>
2014(use awful)
2015
2016;; /bar.* -> /foo
2017(define-page (regexp "/bar.*")
2018  (lambda (_)
2019    (redirect-to "/foo")))
2020
2021(define-page "/foo"
2022  (lambda ()
2023    "foo"))
2024</enscript>
2025
2026
2027==== Request handler hooks
2028
2029Awful provides the possibility of plugin hooks to the request handler,
2030so that deploying multiple awful applications under the same virtual
2031host is possible and easy.
2032
2033===== {{add-request-handler-hook!}}
2034<procedure>(add-request-handler-hook! hook-id proc)</procedure>
2035
2036Adds a hook identified by {{id}} (can be used to remove the hook if
2037necessary). {{proc}} is a two-argument procedure which receives the
2038requested path and its handler.
2039
2040Here's a simple usage example:
2041
2042<enscript highlight=scheme>
2043(add-request-handler-hook!
2044 'foo
2045 (lambda (path handler)
2046   (when (string-prefix? "/foo" path)
2047     (parameterize
2048         ((debug-file "/tmp/foo-debug")
2049          (enable-ajax #t))
2050       (handler))))
2051</enscript>
2052
2053By using request handlers, you can parameterize parameter values in a
2054way that they don't affect other applications.
2055
2056===== {{remove-request-handler-hook!}}
2057<procedure>(remove-request-handler-hook! hook-id)</procedure>
2058
2059Removes the request handler hook identified by {{id}}.
2060
2061
2062==== Web REPL
2063
2064===== {{enable-web-repl}}
2065<procedure>(enable-web-repl path #!key css title)</procedure>
2066
2067Enable the web REPL.  {{path}} is the URL path to the web REPL.
2068
2069The keyword parameter {{css}} is the CSS to be used the the web REPL
2070page (see the documentation for {{html-page}}, from the
2071[[/egg/html-utils|html-utils]] egg, for the {{css}} keyword
2072parameter.)
2073
2074The keyword parameter {{title}} (a string) is the title for the web
2075REPL page (see the documentation for {{html-page}}, from the
2076[[/egg/html-utils|html-utils]] egg, for the {{title}} keyword
2077parameter.)
2078
2079The web REPL is automatically enabled by the awful application server
2080when the {{--development-mode}} is provided (available from
2081{{/web-repl}}).  By default, the fancy editor is used, but can be
2082disabled with the {{--disable-web-repl-fancy-editor}} command line
2083option for the awful application server.
2084
2085
2086==== Session inspector
2087
2088===== {{enable-session-inspector}}
2089<procedure>(enable-session-inspector path #!key css title)</procedure>
2090
2091Enable the session inspector.  {{path}} is the URL path to the session
2092inspector.
2093
2094The keyword parameter {{css}} is the CSS to be used the the session
2095inspector page (see the documentation for {{html-page}}, from the
2096[[/egg/html-utils|html-utils]] egg, for the {{css}} keyword
2097parameter.)
2098
2099The keyword parameter {{title}} (a string) is the title for the
2100session inspector page (see the documentation for {{html-page}}, from
2101the [[/egg/html-utils|html-utils]] egg, for the {{title}} keyword
2102parameter.)
2103
2104The session inspector is automatically enabled by the awful
2105application server when the {{--development-mode}} is provided
2106(available from {{/session-inspector}}).
2107
2108
2109==== Applications
2110
2111===== {{load-apps}}
2112<procedure>(load-apps apps)</procedure>
2113
2114Load the given applications ({{apps}} - a list) (using
2115[[/man/4/Unit eval#load|load]]).
2116
2117
2118===== {{reload-apps}}
2119<procedure>(reload-apps apps)</procedure>
2120
2121The same as {{load-apps}} but also reseting the resources table (the
2122thing that maps URIs to procedures) before loading applications.
2123
2124
2125==== The awful server
2126
2127===== {{awful-start}}
2128<procedure>(awful-start thunk #!key dev-mode? port ip-address (use-fancy-web-repl? #t) privileged-code))</procedure>
2129
2130Starts awful.  This procedure is only useful for standalone
2131applications which intent to embed awful.  For example, the awful
2132application server (the awful command line tool) uses it.
2133
2134This procedure does all the listening, switching user/group and
2135entering the accept loop dance.
2136
2137{{thunk}} is a procedure to be executed upon starting awful.  It can
2138be Scheme code just like any other that can be loaded as an awful
2139application.
2140
2141{{dev-mode?}} (boolean) indicates whether awful should run in development mode.
2142
2143{{port}} (integer) indicates to port to bind to.
2144
2145{{ip-address}} (string) indicates the IP address to bind to.
2146
2147{{use-fancy-web-repl?}} (boolean): indicates whether the web REPL
2148should use the fancy editor.  The default value is {{#t}} (since awful
21490.40.0 -- before that it was {{#f}})
2150
2151{{privileged-code}} (procedure): a thunk that is executed while awful
2152is still running with privileged permissions (when run by the
2153superuser).
2154
2155=== List of macros
2156
2157==== Applications definition
2158
2159===== define-app
2160<syntax>(define-app id matcher: matcher [ parameters: parameters | handler-hook: handler-hook ] body ...)</syntax>
2161
2162This macro can be used to define an awful application. It's a wrapper
2163around {{add-request-handler-hook!}} and should be used when you have
2164multiple awful applications running under the same server, so
2165parameters set for one application don't interfere with other
2166applications' parameters.
2167
2168The idea is that the application's matcher controls when the given
2169parameters or handler-hook will be applied to take effect over the
2170given body expressions.
2171
2172{{id}} (a symbol) is an identifier for the application.
2173
2174{{matcher}} is a Scheme object that is matched against requested
2175paths.  When there is a match, the given parameters or handler-hook
2176are bound/evaluated during the evaluation of {{body}}.  The following
2177types are supported:
2178
2179; 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/"}}.
2180
2181; 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.
2182
2183; 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.
2184
2185
2186{{parameters}} and {{handler-hook}} are mutually exclusive and
2187optional.
2188
2189{{parameters}} is a list of parameter bindings (same syntax as the
2190list given as first argument to {{parameterize}}) that are bound when
2191body is evaluated.
2192
2193{{handler-hook}} is a one-argument procedure which is given the
2194request handler continuation. It is more flexible than {{parameters}},
2195since it can do anything before {{body}} is evaluated, including
2196setting parameters (e.g., using {{parameterize}}).
2197
2198Notice that {{matcher}}, {{parameters}} and {{handler-hook}} are not
2199keyword parameters, they are part of {{define-app}}'s syntax.
2200
2201{{body}} represents the expressions to be evaluated when matcher
2202returns a truthy value.
2203
2204Notice that {{define-app}}'s matcher does not affect the
2205'''definition''' of pages -- they are defined just as if they were
2206defined outside {{define-app}}'s body.
2207
2208Here are some examples, assuming we have three applications, foo, bar
2209and baz, running on the same awful server. The way we "separate"
2210applications is by checking the path prefix, so foo is available from
2211{{/foo}}, bar from {{/bar}} and baz from {{/baz}}. Other criteria can
2212be used, but for simplicity, we'll just use path prefixes.
2213
2214<enscript highlight=scheme>
2215(use awful srfi-13 html-tags awful-sql-de-lite)
2216
2217;;;
2218;;; App foo
2219;;;
2220(define-app foo
2221  matcher: (lambda (path)
2222             (string-prefix? "/foo" path))
2223
2224  parameters: ((enable-ajax #t)
2225               (enable-sxml #t)
2226               (ajax-library "/js/foo.js"))
2227
2228  (define-page "/foo/baz"
2229    (lambda ()
2230      '(p "baz from foo")))
2231
2232  (define-page "/foo/quux"
2233    (lambda ()
2234      '(p "quux from foo")))
2235
2236  )
2237
2238;;;
2239;;; App bar
2240;;;
2241(define-app bar
2242  matcher: (lambda (path)
2243             (string-prefix? "/bar" path))
2244
2245  handler-hook: (lambda (handler)
2246                  (switch-to-sql-de-lite-database)
2247                  (parameterize ((enable-ajax #t)
2248                                 (ajax-library "/js/bar.js")
2249                                 (db-credentials "/var/bar/bar.db"))
2250                    (handler)))
2251
2252  (define-page "/bar/baz"
2253    (lambda ()
2254      (<p> "baz from bar")))
2255
2256  (define-page "/bar/quux"
2257    (lambda ()
2258      (<p> "quux from bar")))
2259
2260  )
2261
2262;;;
2263;;; App baz
2264;;;
2265(define-app baz
2266  matcher: (lambda (path)
2267             (string-prefix? "/baz" path))
2268
2269  (define-page "/baz/foo"
2270    (lambda ()
2271      "foo from baz"))
2272
2273  (define-page "/baz/bar"
2274    (lambda ()
2275      "bar from baz"))
2276
2277  )
2278</enscript>
2279
2280=== Tips and tricks
2281
2282==== Reload applications' code on every request
2283
2284You can use {{add-request-handler-hook!}} to reload the applications'
2285code every time a request is handled by awful.  Here's a simple
2286example:
2287
2288<enscript highlight=scheme>
2289(use awful)
2290
2291(add-request-handler-hook!
2292 'reload-on-request
2293 (lambda (path handler)
2294   (reload-apps (awful-apps))
2295   (handler)))
2296
2297(define-page (main-page-path)
2298  (lambda ()
2299    "1"))
2300</enscript>
2301
2302
2303==== Use {{link}} and {{form}} for links and forms
2304
2305Instead of using {{<a>}} and {{<form>}} for creating links and forms,
2306respectively, consider using the {{link}} and {{form}} procedures
2307instead.  They are specially useful when using sessions, since they
2308transparently handle the session identifier for you.  Even if you
2309don't use sessions, they may save you some work if one day you decide
2310to use sessions (then you won't have do to anything regarding to links
2311and forms).
2312
2313
2314==== Use {{with-request-variables}} when referencing the same request variable multiple times
2315
2316When you need to access the same request variable more than once,
2317consider using {{with-request-variables}}.
2318
2319For example, instead of:
2320
2321<enscript highlight=scheme>
2322(use awful)
2323
2324(enable-sxml #t)
2325
2326(define-session-page "save-and-show-user"
2327  (lambda ()
2328    ($session-set! 'user ($ 'user))
2329    `("Welcome " ,($ 'user "nobody") "!")))
2330</enscript>
2331
2332consider using something like:
2333
2334<enscript highlight=scheme>
2335(use awful)
2336
2337(enable-sxml #t)
2338
2339(define-session-page "save-and-show-user"
2340  (lambda ()
2341    (with-request-variables (user)
2342      ($session-set! 'user user)
2343      `("Welcome " ,(or user "nobody") "!"))))
2344</enscript>
2345
2346
2347==== Use the web REPL and the session inspector for debugging
2348
2349You can simply use the {{--development-mode}} option for the awful
2350application server to enable the web REPL and the session inspector
2351(when {{enable-session}} is {{#t}}).  The development mode allows
2352access to them for the localhost.  When in development mode, the web
2353REPL and the session inspector are available at the {{/web-repl}} and
2354{{/session-inspector}} paths.
2355
2356If you want further flexibility, you can customize the web REPL and
2357the session inspector.
2358
2359Here's a simple recipe to allow access for your local machine to the
2360web REPL ({{/repl}}) and to the session inspector
2361({{/session-inspector}}).
2362
2363<enscript highlight=scheme>
2364(session-inspector-access-control
2365 (lambda ()
2366   (member (remote-address) '("127.0.0.1"))))
2367
2368(enable-session-inspector "/session-inspector")
2369
2370
2371(web-repl-access-control
2372 (lambda ()
2373   (member (remote-address) '("127.0.0.1"))))
2374
2375(enable-web-repl "/repl")
2376</enscript>
2377
2378To access them, just point your browser to
2379{{http://localhost:<port>/repl}} and
2380{{http://localhost:<port>/session-inspector}}, respectively.
2381
2382
2383==== Create custom page definers when {{page-template}} and/or plain {{define-page}} are not enough
2384
2385You can define your own page definers when {{page-template}} or the
2386plain {{define-page}} is not enough for what you need.  Here's an
2387example:
2388
2389<enscript highlight=scheme>
2390(use awful)
2391
2392(enable-sxml #t)
2393
2394(define (define-custom-page path content)
2395  (define-page path
2396    (lambda ()
2397      `(html (body ,(content))))
2398    no-template: #t))
2399
2400(define-custom-page (main-page-path)
2401  (lambda ()
2402    "Hey!"))
2403</enscript>
2404
2405If you access {{http://localhost:8080}} you'll get the following HTML code:
2406
2407  <html>
2408  <body>Hey!</body></html>
2409
2410
2411==== Debugging: error messages on the browser window
2412
2413Error messages right on the browser window can be quite handy for
2414debugging (although not for production environments).  Here's a way to
2415accomplish that:
2416
2417<enscript highlight=scheme>
2418(use awful)
2419
2420(enable-sxml #t)
2421
2422(page-exception-message
2423 (lambda (exn)
2424   `(pre ,(with-output-to-string
2425            (lambda ()
2426              (print-call-chain)
2427              (print-error-message exn))))))
2428
2429(define-page (main-page-path)
2430  (lambda ()
2431    `("Boom!" ,(+ 1 "foo"))))
2432</enscript>
2433
2434This feature is automatically enabled when the awful application
2435server is used with the {{--development-mode}} option.
2436
2437
2438
2439==== Run awful without arguments to quickly share a file
2440
2441When invoked without arguments, awful (the application) starts the web
2442server using the current directory as root path and keeps listening on
2443port 8080.  So, if you want to quickly share a file (or some files),
2444change to the directory containing the files and execute {{awful}}.
2445The access {{http://<host>:8080/<the-file-you-want>}}.
2446
2447
2448==== Awful & SXML
2449
2450Since version 0.36, awful provides SXML support.  To enable it, you
2451can either do it globally, by setting the {{enable-sxml}} parameter to
2452{{#t}}, or in a per-page basis, by binding {{define-page}}'s
2453{{use-sxml}} keyword parameter to {{#t}}.
2454
2455Notice that supporting SXML by default is a goal.  Strings support
2456will be deprecated and removed in future versions.  So, if you are
2457about to start a project using awful, consider setting {{enable-sxml}}
2458to {{#t}}.
2459
2460Here are some examples:
2461
2462===== Globally using SXML
2463
2464<enscript highlight=scheme>
2465(use awful)
2466
2467(enable-sxml #t)
2468
2469(define-page (main-page-path)
2470  (lambda ()
2471    `(div (@ (id "content"))
2472          "Hi, this is awful " ,(awful-version))))
2473</enscript>
2474
2475
2476You can also use [[/egg/html-tags|html-tags]] and
2477[[/egg/html-utils|html-utils]] to generate SXML content:
2478
2479<enscript highlight=scheme>
2480(use awful html-tags)
2481
2482(enable-sxml #t)
2483(generate-sxml? #t) ;; from html-tags
2484
2485(define-page (main-page-path)
2486  (lambda ()
2487    (<div> id: "content"
2488           "Hi, this is awful " (awful-version))))
2489</enscript>
2490
2491
2492===== Using SXML in a per-page basis
2493
2494<enscript highlight=scheme>
2495(use awful html-tags)
2496
2497(define-page "/strings"
2498  (lambda ()
2499    (<div> id: "content"
2500           "Hi, this is awful " (awful-version))))
2501
2502
2503(define-page "/sxml"
2504  (lambda ()
2505    `(div (@ (id "content"))
2506          "Hi, this is awful " ,(awful-version)))
2507  use-sxml: #t)
2508
2509
2510(define-page "/sxml-with-html-tags"
2511  (lambda ()
2512    (parameterize ((generate-sxml? #t))
2513      (<div> id: "content"
2514             "Hi, this is awful " (awful-version))))
2515  use-sxml: #t)
2516</enscript>
2517
2518
2519==== Reloading awful from Emacs
2520
2521Here's a quick hack to reload awful apps from Emacs.  It can be handy
2522when you are developing using awful in development mode
2523({{--development-mode}}, or when you defined your own reload path).
2524
2525<enscript highlight=elisp>
2526(defun awful-reload ()
2527  (interactive)
2528  (shell-command "lynx -dump http://localhost:8080/reload"))
2529
2530(add-hook 'scheme-mode-hook
2531   #'(lambda ()
2532       (local-set-key "\C-cR" 'awful-reload)))
2533</enscript>
2534
2535The code above defines an {{awful-reload}} procedure, which requests
2536the {{/reload}} path (automatically defined by awful when running in
2537development mode) using {{lynx}}.  You can use whatever command line
2538HTTP client you want. {{lynx}} is handy because of the {{-dump}}
2539option, which can be readly displayed by Emacs in the shell command
2540output buffer.
2541
2542Here's a screenshot:
2543
2544[[image:http://parenteses.org/mario/img/awful/awful-reload-emacs.png|Reloading awful apps from Emacs]]
2545
2546
2547==== Performance tweaks
2548
2549* if you don't intend to use static index files, you may configure the
2550[[/egg/spiffy|Spiffy]] {{index-files}} parameter to {{'()}}.  That
2551will disable the lookup for static index files (or you can configure
2552it to contain only the static index files you use).
2553
2554* awful usually performs better with a larger stack size (1MB is a
2555reasonable value).  You can set the runtime stack size with the
2556{{-:s}} command line option (see
2557[[/manual/Using the compiler#runtime-options|the CHICKEN manual
2558page]] for other options):
2559
2560  $ awful -:s1m my-app.so
2561
2562
2563
2564==== Binding URI paths as arguments to page handler procedures
2565
2566<enscript highlight=scheme>
2567(use awful regex srfi-13)
2568
2569(define (define-page* page-path content)
2570  (define-page (regexp (string-append page-path "/*.*"))
2571    (lambda (path)
2572      (let ((url-args
2573             (string-split
2574              ;; Removing `page-path' from the requested path
2575              (string-drop path (string-length page-path))
2576              "/")))
2577        (condition-case
2578         (apply content url-args)
2579         ((exn arity) "invalid arity")
2580         (exn () (signal exn)))))))
2581
2582
2583;;;
2584;;; /page1 ignores all arguments
2585;;;
2586;; http://<server>:<port>/page1 => "no args"
2587;; http://<server>:<port>/page1/1 => "no args"
2588;; http://<server>:<port>/page1/1/2 => "no args"
2589(define-page* "/page1"
2590  (lambda _
2591    "no args"))
2592
2593
2594;;;
2595;;; /page2 requires exactly one argument
2596;;;
2597;; http://<server>:<port>/page2 => "invalid arity"
2598;; http://<server>:<port>/page2/1 => "foo=1"
2599;; http://<server>:<port>/page1/1/2 => "invalid arity"
2600(define-page* "/page2"
2601  (lambda (foo)
2602    (conc "foo=" foo)))
2603
2604
2605;;;
2606;;; /page3 requires one argument (the other is optional).  Ignores the
2607;;; rest.
2608;;;
2609;; http://<server>:<port>/page3 => "invalid arity"
2610;; http://<server>:<port>/page3/1 => "foo=1, bar=#f"
2611;; http://<server>:<port>/page1/1/2 => "foo=1, bar=2"
2612;; http://<server>:<port>/page1/1/2/3 => "foo=1, bar=2"
2613(define-page* "/page3"
2614  (lambda (foo #!optional bar)
2615    (conc "foo=" foo ", bar=" bar)))
2616
2617
2618;;;
2619;;; /page4: all arguments are optional (get bound if given).
2620;;;
2621;; http://<server>:<port>/page4 => "foo=#f, bar=#f"
2622;; http://<server>:<port>/page4/1 => "foo=1, bar=#f"
2623;; http://<server>:<port>/page4/1/2 => "foo=1, bar=2"
2624;; http://<server>:<port>/page4/1/2/3 => "foo=1, bar=2"
2625(define-page* "/page4"
2626  (lambda (#!optional foo bar)
2627    (conc "foo=" foo ", bar=" bar)))
2628</enscript>
2629
2630
2631==== Awful badge
2632
2633Here's a suggestion:  [[image:http://parenteses.org/mario/img/thats-awful.png|That's awful!]]
2634
2635=== Examples
2636
2637Here are some simple examples using assorted awful features.
2638
2639==== Example with AngularJS
2640
2641Assuming you have
2642[[https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js|angular.min.js]]
2643in the {{root-path}} (the current directory, by default) and the code
2644below is in a file {{angular-app.scm}}:
2645
2646<enscript highlight=scheme>
2647(use html-utils ;; you'll need html-utils >= 0.10
2648     awful)
2649
2650(enable-sxml #t)
2651
2652(define-page (main-page-path)
2653  (lambda ()
2654    (html-page
2655     `(div (@ (class "container"))
2656           "Name: " (input (@ (type "text")
2657                              (ng-model "name")))
2658           "{{ name }}")
2659     html-attribs: '((ng-app))
2660     doctype: "<!DOCTYPE html>"
2661     headers: (include-javascript "/angular.min.js")))
2662  no-template: #t)
2663</enscript>
2664
2665Alternatively, you can set the {{page-template}} parameter:
2666
2667<enscript highlight=scheme>
2668(use html-utils ;; you'll need html-utils >= 0.10
2669     awful)
2670
2671;; Configure page-template to set ng-app as attribute for the html tag
2672(page-template
2673 (lambda (content . args)
2674   (apply html-page
2675          (append (list content html-attribs: '((ng-app)))
2676                  args))))
2677
2678(enable-sxml #t)
2679
2680(define-page (main-page-path)
2681  (lambda ()
2682    `((div (@ (class "container"))
2683           "Name: " (input (@ (type "text")
2684                              (ng-model "name")))
2685           "{{ name }}")))
2686  doctype: "<!DOCTYPE html>"
2687  headers: (include-javascript "/angular.min.js"))
2688</enscript>
2689
2690To run the example, execute:
2691
2692  $ awful angular-app.scm
2693
2694and use your favorite web browser to access
2695{{http://localhost:8080/}}.
2696
2697
2698==== Number guessing game
2699
2700A screencast showing this example is available at
2701[[http://parenteses.org/mario/awful/awful-guess.ogv|http://parenteses.org/mario/awful/awful-guess.ogv]]
2702
2703This examples shows a simple guessing game. A random number is
2704generated on the server side and the user tries to guess it.  It shows
2705some basic ajax features.
2706
2707<enscript highlight=scheme>
2708(use awful)
2709
2710(enable-sxml #t)
2711
2712(define (prompt-guess)
2713  '(input (@ (type "text") (id "guess"))))
2714
2715(define-page (main-page-path)
2716  (lambda ()
2717    (ajax "try-guess" 'guess 'change
2718          (lambda ()
2719            (let ((guess ($ 'guess as-number))
2720                  (thinking (random 10)))
2721              `(p ,(if (and guess (= guess thinking))
2722                       "You guessed it right!"
2723                       `("You guessed it wrong. I'm thinking " ,thinking ".")))))
2724          target: "verdict"
2725          arguments: '((guess . "$('#guess').val()")))
2726    `((p "Guess the number I'm thinking:")
2727      ,(prompt-guess)
2728      (div (@ (id "verdict")))))
2729  use-ajax: #t)
2730</enscript>
2731
2732To run it, execute:
2733
2734  $ awful number-guess.scm
2735
2736(considering you saved the code above in a file called
2737{{number-guess.scm}}), then access {{http://localhost:8080}}.
2738
2739
2740
2741==== Sandboxed Chicken Web REPL
2742
2743It shows how to implement a very simple web-based Chicken REPL using a
2744sandbox environment (see the
2745[[/egg/sandbox|sandbox egg]] documentation) for
2746safe evaluation.
2747
2748The idea is to have a web page with an input box. Users type the forms
2749they want to evaluate and submit them to the server. The server
2750evaluates the given forms in a sandbox environment and return the
2751results.
2752
2753Here's the commented code:
2754
2755<enscript highlight=scheme>
2756(use awful sandbox)
2757
2758(enable-sxml #t)
2759
2760;; Here we define the REPL page.  It uses the session to store the
2761;; sandboxed environment.  By default, the `main-page-path' parameter
2762;; value is "/".
2763(define-session-page (main-page-path)
2764  (lambda ()
2765
2766    ;; Create the sandbox environment (if it does not exist yet) and
2767    ;; store it in the user session.
2768    (unless ($session 'sandbox-env)
2769      ($session-set! 'sandbox-env
2770                     (make-safe-environment
2771                      parent: default-safe-environment
2772                      mutable: #t
2773                      extendable: #t)))
2774
2775    ;; Here we set an ajax handler for the REPL expressions
2776    ;; submission.  When users change the REPL input widget (i.e., by
2777    ;; pressing ENTER), the contents of the text input field are
2778    ;; submitted and handled by the procedure given as the fourth
2779    ;; argument to `ajax'.
2780    (ajax "eval" 'repl-input 'change
2781          (lambda ()
2782
2783            ;; This binds the variable `repl-input' from the POST
2784            ;; method the the `repl-input' Scheme variable
2785            (let ((repl-input ($ 'repl-input)))
2786
2787              ;; We'd better handle exceptions when trying to
2788              ;; evaluate the expressions given by users.
2789              (handle-exceptions
2790               exn
2791               ;; If something goes wrong, we print the error message
2792               ;; and the call chain.
2793               `(pre ,(with-output-to-string
2794                        (lambda ()
2795                          (print-error-message exn)
2796                          (print-call-chain))))
2797               ;; Here we try to evaluate the given expression in the
2798               ;; sandboxed environment stored in the user session.
2799               ;; The `repl-output' page div is updated with the result.
2800               `(pre ,(safe-eval
2801                       (with-input-from-string repl-input read)
2802                       fuel: 100
2803                       allocation-limit: 100
2804                       environment: ($session 'sandbox-env))))))
2805
2806          ;; Here we pass the contents of the text input to the ajax
2807          ;; handler.  The default HTTP method used by `ajax' is POST.
2808          arguments: `((repl-input . "$('#repl-input').val()"))
2809
2810          ;; The output of the ajax handler updates the `repl-output'
2811          ;; page div.
2812          target: "repl-output")
2813
2814    ;; Here's what is displayed to users
2815    `((h1 "Sandboxed Chicken web REPL")
2816      (input (@ (type "text") (id "repl-input")))
2817      (div (@ (id "repl-output")))))
2818
2819  ;; This tells `define-session-page' to link the page to jQuery
2820  use-ajax: #t)
2821</enscript>
2822
2823To run the code above you'll need to install awful and sandbox:
2824
2825  $ chicken-install awful sandbox
2826
2827Then (considering you save the code above in a file called {{web-sandbox.scm}}), run:
2828
2829  $ awful web-sandbox.scm
2830
2831and access {{http://localhost:8080}}.
2832
2833
2834Here are some screenshots of the code above running on Firefox:
2835
2836[[image:http://gazette.call-cc.org/img/10/web-sandbox.png|Screenshot of the sandboxed web REPL running on Firefox]]
2837
2838If you try something nasty, the sandbox will abort the evaluation and you'll get an error message and the call chain:
2839
2840[[image:http://gazette.call-cc.org/img/10/web-sandbox-loop.png|Screenshot of the sandboxed web REPL running on Firefox]]
2841
2842We can also compile the web application:
2843
2844 $ csc -s web-sandbox.scm
2845 $ awful web-sandbox.so
2846
2847
2848==== Color chooser
2849
2850Here's an example provided by
2851[[/users/christian-kellermann|Christian Kellermann]] demonstrating an ajax-based color chooser:
2852
2853<enscript highlight=scheme>
2854(use awful)
2855
2856(enable-sxml #t)
2857
2858(define color-table
2859  '("f63353" "fead76" "107279" "10fabc" "1181bf" "120902" "129105"
2860    "131848" "13a04b" "1427ee" "14a8b1" "1532d4" "15bcf7" "16671a"
2861    "16c13d" "175b60" "17d583" "186fa6" "18ecc9" "1973ec"))
2862
2863(define (color-picker counter color)
2864  `(div (@ (class "color-box")
2865           (style ,(string-append "background-color: #" color)))
2866        (input (@ (type "text")
2867                  (id ,(conc "change-color-" counter))
2868                  (value ,color)))))
2869
2870(define (make-color-chooser counter c)
2871  (ajax "ajax" (conc "#change-color-" counter) 'change
2872        (lambda ()
2873          (let ((color (or ($ 'color) c))
2874                (counter ($ 'counter)))
2875            (color-picker counter color)))
2876        target: (conc "color-box-" counter)
2877        arguments: `((color . ,(conc  "$('#change-color-" counter "').val()"))
2878                     (counter . ,counter))
2879        live: #t)
2880  `(div (@ (id ,(conc "color-box-" counter)))
2881        ,(color-picker counter c)))
2882
2883(define-page (main-page-path)
2884  (lambda ()
2885    (map (let ((counter -1))
2886           (lambda (c)
2887             (set! counter (add1 counter))
2888             (make-color-chooser counter c)))
2889         color-table))
2890  use-ajax: #t)
2891</enscript>
2892
2893Here's a screenshot:
2894
2895[[image:http://parenteses.org/mario/img/awful/color-chooser.png|Awful color chooser]]
2896
2897To run this example (considering you save the code above in a file called {{color-chooser.scm}}):
2898
2899  $ awful color-chooser.scm
2900
2901then access {{http://localhost:8080}}.  You can change the colors by
2902editing the input boxes then pressing enter.
2903
2904
2905==== Fortune server
2906
2907This example is a fortune server in awful.  It demonstrates some handy
2908awful features like database access and ajax.  You'll need the
2909[[/egg/awful-sql-de-lite|awful-sql-de-lite]]
2910egg and its dependencies (which should be automatically installed by
2911{{chicken-install}}).
2912
2913Here are instructions to install and use it:
2914
29151. Install [[/egg/awful-sql-de-lite|awful-sql-de-lite]]
2916
2917   $ chicken-install awful-sql-de-lite
2918
2919
29202. Create the fortunes database (see the code below):
2921
2922   $ csi -s create-database.scm
2923
2924
29253. Run the fortune server (see the code below):
2926
2927   $ awful fortune-server.scm
2928
2929
2930Here's the code for {{create-database.scm}} which creates and populates the fortune database:
2931
2932<enscript highlight=scheme>
2933(use sql-de-lite posix)
2934
2935(define fortunes
2936  '(("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."
2937     "Brian Kernighan")
2938    ("In order to understand recursion, one must first understand recursion.")
2939    ("If debugging is the process of removing software bugs, then programming must be the process of putting them in."
2940     "Edsger Dijkstra")
2941    ("Controlling complexity is the essence of computer programming."
2942     "Brian Kernigan")
2943    ("The function of good software is to make the complex appear to be simple."
2944     "Grady Booch")
2945    ("That's the thing about people who think they hate computers.  What they really hate is lousy programmers."
2946     "Larry Niven")
2947    ("First learn computer science and all the theory.  Next develop a programming style.  Then forget all that and just hack."
2948    "George Carrette")
2949    ("To iterate is human, to recurse divine."
2950    "L. Peter Deutsch")
2951    ("The best thing about a boolean is even if you are wrong, you are only off by a bit.")
2952    ("Optimism is an occupational hazard of programming; feedback is the treatment."
2953     "Kent Beck")
2954    ("Simplicity is prerequisite for reliability."
2955     "Edsger W. Dijkstra")
2956    ("Simplicity is the ultimate sophistication."
2957     "Leonardo da Vinci")
2958    ("The unavoidable price of reliability is simplicity."
2959     "C.A.R. Hoare")
2960    ("The ability to simplify means to eliminate the unnecessary so that the necessary may speak."
2961     "Hans Hoffmann")
2962    ("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."
2963     "Chris Sacca")))
2964
2965(delete-file* "fortunes.db")
2966
2967(let ((db (open-database "fortunes.db")))
2968  (exec (sql db "create table fortunes(sentence text, author text)"))
2969  (for-each (lambda (fortune)
2970              (let* ((sentence (car fortune))
2971                     (author (cdr fortune))
2972                     (statement
2973                      (string-append
2974                       "insert into fortunes (sentence, author) values (?,?)")))
2975                (exec (sql db statement)
2976                      sentence
2977                      (if (null? author) "" (car author)))))
2978            fortunes)
2979  (close-database db))
2980</enscript>
2981
2982Here's the code for the fortune server:
2983
2984<enscript highlight=scheme>
2985(use awful awful-sql-de-lite)
2986
2987(enable-sxml #t)
2988(enable-db)
2989(db-credentials "fortunes.db")
2990
2991(define (random-fortune)
2992  (car ($db "select sentence, author from fortunes order by random() limit 1")))
2993
2994(define-page (main-page-path)
2995  (lambda ()
2996    (ajax "new-fortune" 'new-fortune 'click
2997          (lambda ()
2998            (let ((fortune (random-fortune)))
2999              `((sentence . ,(car fortune))
3000                (author . ,(cadr fortune)))))
3001          update-targets: #t)
3002
3003    `(div (@ (id "content"))
3004          (div (@ (id "sentence"))
3005               "Click the button below to get a new fortune")
3006          (div (@ (id "author")))
3007          (button (@ (id "new-fortune")) "New fortune")))
3008  css: "fortune.css"
3009  use-ajax: #t
3010  charset: "utf-8")
3011</enscript>
3012
3013
3014The contents of the {{fortune.css}} file are:
3015
3016<enscript highlight=css>
3017body
3018{ font-family: arial, verdana, sans-serif;
3019}
3020
3021#sentence
3022{ width: 20em;
3023  background-color: #DEE7EC;
3024  padding: 6px;
3025  min-height: 7em;
3026}
3027
3028#author
3029{ width: 20em;
3030  min-height: 2em;
3031  padding: 6px;
3032  background-color: #eee;
3033}
3034</enscript>
3035
3036Here's a screenshot:
3037
3038[[image:http://parenteses.org/mario/img/awful/fortune-server.png|Awful fortune server]]
3039
3040
3041==== I-wonder
3042
3043I-wonder is a simple awful example application which uses SQLite as
3044storage (with the [[/egg/sql-de-lite|sql-de-lite]] egg).
3045
3046You can find the code for that application on GitHub: [[https://github.com/mario-goulart/i-wonder|https://github.com/mario-goulart/i-wonder]]
3047
3048Here's a screenshot
3049
3050[[image:http://parenteses.org/mario/img/awful/i-wonder.png|I-wonder]]
3051
3052=== The name
3053
3054Awful doesn't mean anything special.  It's just awful.  But folks on freenode's #chicken (IRC) have suggested some acronym expansions:
3055
3056* A Whole Freaking Universe of Lambdas
3057* Authored Without Full Understanding of Logic
3058* Another Web Framework Understating Logic
3059* All Worthless Frameworks Unchain Laziness
3060* Armed With Flimsy Utility Lisp
3061* Awful Will Fed Up Lispers
3062* Awful Wildly Finalizes Unfinished Loops
3063* Another Widely Foolish Unknown Language
3064* Ain't Work For Unpleasant Laywers
3065* Aliens Would Find it Utterly Lame
3066* Aren't We Funny and Uncaring Lurkers
3067* Awful Will F*** Up Logic
3068* Awful Will Fart Upon Leaving
3069* Again Web Frameworks Underscore Lameness
3070* Attention While Fully Utilizing Laziness
3071* Another Webserver F***ing Up the Line
3072* Again We Forget Unclosed Lambdas
3073* All Web Features Understood Losslessly
3074* Anything With Fully Universal Lambdas
3075* Again We Fail Under Load
3076* Apocalyptic Warthogs Find Undiscovered Lands
3077* Accessible Web Framework Using Lisp
3078* Another Weird Framework Using Lisp
3079* All Waffles Fear Unicorn Landings
3080* A Working Facility Underscoring Laziness
3081* Another Webbot Flapping Under Lines
3082* Anybody Will Fake Unrealistic Loveletters
3083* Armadillos Would First Use Legs
3084* Astonishing Whales Fill Up Lakes
3085* Alternative Way to F*** Up Lisp
3086* Another Way to Find Undressed Ladies
3087* Amazing! Wonderful! Fantastic! Unbelievable! Lame.
3088* All Wonders Feel Useless Later
3089* Amazingly Wonderful Feeling, Using Lambdas
3090* Alligators Will Fear Us, Lunatics
3091* All Wussies Fear Ultimate Lambda
3092* Animals Will Find Us Letal
3093* Advanced Web Framework: Ultimate Lucubration
3094* Awful Will Feed Urban Lethargy
3095* Argument With Focus Upon Labelling
3096* Another Word Faking Unpremeditated Label
3097* Again We Find it Utterly Useless
3098* Ain't Work For Unattractive Ladies
3099* A Way For Using Lambdas
3100* Awful Way For Using Lambdas
3101* Apparently We Freaks Understand Lambdas
3102* Again We Foolishly Use Lists
3103* At Work Fools Use Lisp
3104* Again We Foolishly Use Lisp
3105* Another Wimp Fall Upon Lisp
3106* Accepting Whatever Fools Undertake Lightly
3107* Absurd Word For Unnatural Lingo
3108* Alternative Word For Useless Loser
3109* Acronym With Filled Up Letters
3110* Acronym We Find Utterly Lame
3111* Another Webserver Functioning Until Launched
3112* Applications With Familiar, Understandable Language
3113* (Awful Words Forming Useless List)
3114* All Who Force Unusual Layout
3115* Again We Fear Undescribable Lamenting
3116* Awful Will Favour Ugly Layouts
3117* Apes With Frequent Uncontrolled Lunacy
3118
3119==== Acknowledgements (IRC nicknames on freenode's #chicken):
3120
3121
3122* C-Keen
3123* DerGuteMoritz
3124* elderK
3125* elf
3126* florz
3127* merlincorey
3128* sjamaan
3129
3130=== FAQ (aka Fakely Asked Questions)
3131
3132==== How does awful bind URIs to files/directories on the filesystem and procedures?
3133
3134Explanation by example:
3135
3136When 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:
3137
3138* 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}}.
3139
3140* 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)
3141
3142* 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}})
3143
3144* 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}}.
3145
3146=== Known bugs and limitations
3147
3148* Awful currently doesn't detect if cookies are enabled on the client side.
3149
3150* 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]].
3151
3152* When {{define-page}}'s {{no-template}} is not false,
3153{{add-javascript}} and ajax-related features for {{define-page}}
3154won't be effective for the page in question.
3155=== License
3156
3157  Copyright (c) 2010-2014, Mario Domenech Goulart
3158  All rights reserved.
3159 
3160  Redistribution and use in source and binary forms, with or without
3161  modification, are permitted provided that the following conditions
3162  are met:
3163  1. Redistributions of source code must retain the above copyright
3164     notice, this list of conditions and the following disclaimer.
3165  2. Redistributions in binary form must reproduce the above copyright
3166     notice, this list of conditions and the following disclaimer in the
3167     documentation and/or other materials provided with the distribution.
3168  3. The name of the authors may not be used to endorse or promote products
3169     derived from this software without specific prior written permission.
3170 
3171  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
3172  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3173  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3174  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
3175  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3176  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
3177  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3178  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3179  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3180  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
3181  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3182
3183=== Version history
3184
3185===== version 0.42.0
3186
3187* Use SPIFFY_TEST_PORT environment variable's value (if provided) for tests
3188
3189* 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}}.
3190
3191* Bug fix for {{form}} in SXML mode. Thanks to Thomas Hintz for spotting that issue.
3192
3193* {{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.
3194
3195* Add {{strict}} keyword parameter for define-page and ajax & friends
3196
3197For convenience, awful sloppily considered requests for files and
3198directories to be equivalent.  For example, if a page was defined with
3199a {{"/foo"}} matcher, a request for {{"/foo/"}} would be handled by
3200{{"/foo"}}'s handler.
3201
3202That's not always desired.  For example, consider this case:
3203
3204  (define-page (irregex "/[^/]*") identity)
3205
3206We want to specify that, e.g., requests for {{/foo}} should be
3207handled, but requests for {{/foo/}} should ''not'' be handled.  However,
3208since awful tries to find a handler by stripping the trailing slash, a
3209request for {{/foo/}} would actually be handled by the handler for
3210{{(irregex "/[^/]*")}}, even if the regex specified that paths with a
3211trailing slash should not match.
3212
3213To work around that inconsistency, a new keyword parameter has been
3214added to {{define-page}}, {{ajax}}, {{periodical-ajax}} and
3215{{ajax-link}}: {{strict}} (default: {{#f}}, for backward
3216compatibility).  If the {{strict}} keyword parameter is truthy, awful
3217will not try to find a handler for the requested path by removing the
3218trailing slash.
3219
3220With this change, the format of the resources table has changed too.
3221Now the value part of hash table items is a pair whose car is the
3222resource handler and the cdr is a boolean indicating whether the
3223resource is "strict" or not.
3224
3225
3226===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=32298|version 0.41.0]]
3227
3228* The deprecated procedure {{sql-quote}} has been removed
3229
3230* Set the default value for {{$db}}'s {{default}} keyword param as {{'()}}
3231
3232To be consistent with the db-support eggs for awful.
3233
3234'''WARNING''': this change may break your code!  In case of an empty
3235result set from a query, {{$db}} will now return {{'()}} instead of
3236{{#f}}.
3237
3238This change can be specially harmful in case you have something like
3239
3240<enscript highlight=scheme>
3241         (or ($db "some query") "something")
3242</enscript>
3243
3244In this example, if the query returns an empty result set, that
3245expression would produce:
3246
3247* in older awful versions: {{"something"}}
3248* in awful versions with this change: {{'()}}
3249
3250To work around the incompatible behaviors, you can:
3251
3252* require awful 0.41.0 in you .meta file
3253* always provide a value for {{$db}}'s {{default}} keyword parameter
3254
3255
3256===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=30483|version 0.40.0]]
3257* SSQL support for {{$db}} and {{$db-row-obj}}
3258* Full support for static pages generation (via [[/egg/awful-static-pages|awful-static-pages]])
3259* {{--privileged-code}} now accepts multiple files (comma-separated)
3260* Bug fixes in web-repl when in SXML mode
3261* The default value for {{use-fancy-web-repl?}} is now {{#t}} in {{awful-start}} (to match the command line application's default behavior)
3262* jQuery updated to 1.11.0
3263
3264===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=30336|version 0.39.2]]
3265* jQuery's {{on}} method support for {{ajax}} & friends
3266* {{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)
3267* 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
3268
3269===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=29489|version 0.39.1]]
3270* Update jQuery to version 1.10.2
3271* Bug fix: {{page-path}} should return {{(app-root-path)}} when given {{"/"}}
3272* Bug fix: check to make sure redirect-to-login-page always generates HTML (patch by Hugo Arregui)
3273
3274===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=28751|version 0.39]]
3275
3276* The default methods for {{define-page}} are now HEAD and GET (thanks to Thomas Hintz)
3277* Bug fix for {{link}} in SXML mode
3278* Add {{define-app}} macro
3279* Add {{literal-script/style?}} parameter (suggested by John J. Foerch)
3280* Add {{add-css}} procedure (suggested by John J. Foerch)
3281
3282
3283===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=28237|version 0.38.2]]
3284
3285* 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
3286
3287
3288===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27797|version 0.38.1]]
3289
3290* Fix bug in handler for {{/reload}} when in development mode and in SXML mode
3291* Versions now have a second dot for bugfix releases
3292
3293
3294===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27701|version 0.38]]
3295
3296* Fix bug in {{define-page}} when page handlers return procedures
3297
3298
3299===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27693|version 0.37]]
3300
3301* Fix {{page-exception-message}} when in development mode and using SXML (thanks to sECuRE for catching that)
3302
3303
3304===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=27510|version 0.36]]
3305
3306* 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.
3307* {{++}} and {{concat}} have been deprecated (they are still available, but will be removed in future versions).
3308* jQuery updated to version 1.8.2
3309
3310
3311===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=26831|version 0.35]]
3312
3313* Added {{awful-resources-table}}
3314* Added {{set-page-title!}} (thanks to John J. Foerch for suggesting that)
3315* {{define-page}}'s first argument (the path matcher) can now be a procedure (thanks to John J. Foerch for suggesting that)
3316* The return value of the second argument to {{define-page}} can now be a procedure
3317* {{add-request-handler-hook!}} overwrites hooks with the same name instead of adding multiple copies
3318* {{define-page}}'s {{use-ajax}} keyword parameter can also be bound to a string indicating the path to the ajax library
3319* Code moved to GitHub
3320
3321
3322===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25890|version 0.34]]
3323* Don't check {{current-effective-user-id}} on windows, since it is not available on that platform.  Reported by Karl_H on #chicken.
3324* 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.
3325
3326
3327===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25689|version 0.33]]
3328* jQuery updated to version 1.7.1
3329* Added {{session-cookie-setter}} (thanks to Thomas Hintz)
3330* Added {{event}} argument to anonymous JavaScript function given as argument to {{bind}}/{{live}} ({{ajax}} and friends).  Patch by Thomas Hintz.
3331* The {{method}} keyword parameter for {{define-page}} and {{ajax}} & friends can be bound to a list of methods.  Methods are now case insensitive.
3332
3333===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=25073|version 0.32]]
3334* 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.
3335* Added {{error-handler}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}} (suggested by Thomas Hintz)
3336* {{ajax}} and friends send {{Content-Type: application/json}} when {{update-targets}} is non-#f
3337* {{ajax}} bugfix: only opens db connection and refresh session when the page access is allowed
3338* The default value for {{awful-backlog}} has been set to 100
3339* Updated jQuery from version 1.5.2 to 1.6.3
3340* Dropped {{-lambda-lift}} build option
3341* Added the {{reload-apps}} procedure. {{load-apps}} no longer resets the resources table
3342* {{awful-start}} requires a thunk as argument. With this, awful can be embedded into standalone applications
3343
3344
3345===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=23515|version 0.31]]
3346* 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.
3347* Updated jQuery from version 1.5.1 to 1.5.2.
3348* Better support for multiple applications under the same virtual host ({{add-request-handler-hook!}} and {{remove-request-handler-hook!}})
3349* {{$db}} checks if database access is enabled via {{(enable-db)}} and throws an error if it is not.
3350* Fixed critical bug regarding to parameters and thread reuse by Spiffy
3351* Fixed {{redirect-to}} but introduced in version 0.29
3352
3353===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=23075|version 0.30]]
3354* The {{(ajax-library)}} is always linked before any other scripts and JavaScript code in the headers (i.e., when {{(javascript-position)}} is {{top}}).
3355* Ajax-related procedures simplifications and bugfix in the session awareness code when called from {{define-session-page}}.
3356
3357===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=22907|version 0.29]]
3358* Updated jQuery from version 1.5.0 to 1.5.1.
3359* {{ajax}} and {{periodical-ajax}} bugfix (for situations when they are used simultaneously, or {{periodical-ajax}} and {{add-javascript}}).
3360* The default URI for {{ajax-library}} is now protocol-relative (thanks to Peter Bex).
3361* Added the {{javascript-position}} parameter.
3362
3363===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=22639|version 0.28]]
3364* Updated jQuery from version 1.4.3 to 1.5.0.
3365* {{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).
3366* Added the {{cache}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}}.
3367* 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).
3368* 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.
3369* {{define-session-page}} bug fix (it was not properly obtaining the session identifier).
3370
3371
3372===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=20689|version 0.27]]
3373* Require the {{regex}} egg, for chickens >= 4.6.2
3374
3375===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=19844|version 0.26]]
3376* {{define-page}} allows page redefinitions
3377* Added the {{undefine-page}} procedure
3378* 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.
3379* Added the following parameters, related to the fancy web REPL: {{enable-web-repl-fancy-editor}} and {{web-repl-fancy-editor-base-uri}}.
3380* Bug fix for the development mode: requests to the {{/reload}} path killed {{/web-repl}} and {{/session-inspector}}
3381
3382===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=19496|version 0.25]]
3383* 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.
3384* The awful application server now supports the {{--ip-address}} and {{--port}} command line options.
3385* {{use-ajax}} keyword parameter for {{define-page}} (for when {{enable-ajax}} is {{#f}} and you need ajax for some specific pages only)
3386* Added {{awful-response-headers}} and {{development-mode?}} parameters
3387
3388===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18903|version 0.24]]
3389* 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.
3390* initial support for HTTP redirection via {{redirect-to}}.
3391* web-repl and session-inspector beautification
3392* web-repl and session inspector provide a {{headers}} keyword parameter
3393* fixes for {{define-page}} regarding to regex-based paths
3394* {{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
3395* awful (the application) handles the {{-v}} and {{--version}} command line options
3396
3397===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18559|version 0.23]]
3398* added the {{update-targets}} keyword parameter for {{ajax}}, {{periodical-ajax}} and {{ajax-link}} procedures (multiple targets update support)
3399* added the {{debug-resources}} parameter for debugging the resources table
3400* 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.
3401* 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}}).
3402* 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.
3403* {{ajax}} bugfix regarding to session identifiers (could cause "Invalid session ID" errors in some cases, specially with {{define-session-page}}).
3404* 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?'')
3405
3406===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18328|version 0.22]]
3407* bug fix: fixed unintended shadowing of {{js}} in ajax
3408* added the {{prelude}} keyword parameter for {{ajax}}, {{periodical-ajax}} and {{ajax-link}}
3409* {{$db}} supports the {{values}} keyword parameter (patch by Stephen Eilert)
3410* awful (the application) can now be invoked without arguments
3411* awful (the application) handles {{-h}} and {{--help}}
3412* dropped [[/eggref/4/jsmin|jsmin]] requirement
3413
3414===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18149|version 0.21]]
3415* ajax and main page redirection issues fixes
3416
3417===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18051|version 0.20]]
3418* {{page-access-control}} controls access to pages even when no session is in use
3419* '''Warning''': the following parameters have been removed: {{enable-reload}}, {{reload-path}} and {{reload-message}}.  Now the way to define reloaders is via {{define-page}}.
3420* new parameter: {{awful-apps}} (a list of awful applications as passed to the awful server)
3421
3422===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18040|version 0.19]]
3423* bug fix for {{(reload-path)}} handler
3424
3425===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=18030|version 0.18]]
3426* support for regex-based page paths (see {{define-page}})
3427* {{define-page}} checks whether the second arg is a procedure.
3428* use {{-O3 -lambda-lift}} instead of {{-O2}} for compilation
3429* {{main-page-path}} redirection made with code stolen from [[/egg/spiffy|spiffy]]'s {{send-response}}
3430
3431===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17510|version 0.17]]
3432* .meta bug fix.  postgresql is not required as a dependency (thanks to Stephen Pedrosa Eilert for pointing this issue).
3433
3434===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17393|version 0.16]]
3435* added {{define-session-page}}
3436* bug fix for {{link}}
3437
3438===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17383|version 0.15]]
3439* jQuery updated to 1.4.2 ({{ajax-library}}).
3440
3441===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17350|version 0.14]]
3442* {{link}}'s {{args}} keyword parameter renamed to {{arguments}} (the same as {{ajax}}'s).
3443
3444===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17346|version 0.13]]
3445* Session-aware {{link}} and {{form}} procedures.  Bug fix for {{ajax-link}} (was not passing the {{class}} keyword argument to <a>).
3446
3447===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17278|version 0.12]]
3448* Containers for user and password fields ({{login-form}})
3449
3450===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17275|version 0.11]]
3451* awful sets Spiffy's {{root-path}} to {{(current-directory)}}
3452
3453===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17186|version 0.10]]
3454* 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.
3455* Removed requirement for postgresql
3456* {{enable-db}} is now a procedure (not a parameter as before) and accepts no arguments
3457
3458===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17172|version 0.9]]
3459* {{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.
3460
3461===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17149|version 0.8]]
3462* jQuery updated to 1.4.1 ({{ajax-library}}).
3463* support for jQuery's {{live}} method ({{live}} keyword parameter for {{ajax}}, {{ajax-link}} and {{periodical-ajax}}).  See [[http://api.jquery.com/live/]]
3464* bug fixes: {{periodical-ajax}} and {{ajax-link}} propagate {{vhost-root-path}} to {{ajax}}
3465* added {{awful-start}} and dropped spiffy requirement for awful (the server)
3466* dropped requirement for miscmacros
3467* added more ajax tests
3468
3469===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17139|version 0.7]]
3470* {{ajax-link}} accepts all {{<a>}}'s keyword arguments
3471
3472===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17134|version 0.6]]
3473* Explicitly depends on [[/egg/http-session|http-session]] 2.0
3474
3475===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17130|version 0.5]]
3476* Reload handler register the reload path after reloading.
3477
3478===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17127|version 0.4]]
3479* {{disable-reload?}} renamed to {{enable-reload}}.  {{enable-reload}} is {{#f}} by default.
3480
3481===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17122|version 0.3]]
3482* {{awful}} (the server) allows applications to use Chicken syntax ({{use}}, {{include}}, etc.)
3483
3484===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17120|version 0.2]]
3485* Added JavaScript compression support
3486
3487===== [[http://wiki.call-cc.org/eggref/4/awful?action=show&rev=17109|version 0.1]]
3488* Initial release
3489
Note: See TracBrowser for help on using the repository browser.