source: project/wiki/eggref/4/spiffy @ 20962

Last change on this file since 20962 was 20962, checked in by sjamaan, 11 years ago

Update spiffy changelog

File size: 30.7 KB
Line 
1[[tags: egg]]
2
3== Spiffy
4
5[[toc:]]
6
7=== Description
8
9A small web-server written in [[http://www.call-with-current-continuation.org|Chicken]].
10
11=== Author
12
13[[/users/felix-winkelmann|Felix Winkelmann]].
14Currently maintained by [[/users/peter-bex|Peter Bex]].
15
16=== Requirements
17
18Requires the [[intarweb]], [[uri-common]], [[defstruct]], [[matchable]]
19and [[sendfile]] extensions.
20
21=== Documentation
22
23Spiffy is a web-server library for the Chicken Scheme system. It's
24quite easy to set up and use (whether as a library or a standalone
25server application) and it can be customized in numerous ways.
26
27=== Starting the server
28
29<procedure>(start-server [port: port-number] [ssl-client-context: ctx] [ssl-pemfile: pemfile] [ssl-keyfile: keyfile] [bind-address: address])</procedure>
30
31Starts the server, to listen on the given port. Other configuration
32can be tweaked through SRFI-39 parameters. These are listed below.
33Once the server is started, server behaviour can be controlled through
34these parameters as well. By default, Spiffy will only serve static
35files. On directories, it will give a "403 forbidden", unless there
36is an index-file. If there is, that file's contents will be shown.
37
38All arguments directly supplied to {{start-server}} override the
39configuration parameter values.
40
41{{Port-number}} defaults to the value of {{server-port}} (see below).
42{{Ssl-pemfile}} defaults to the value of {{server-ssl-pemfile}} (see below).
43{{Ssl-keyfile}} defaults to the value of {{server-ssl-keyfile}} (see below).
44{{Ssl-client-context}} defaults to the value of {{server-ssl-client-context}} (see below).
45{{Bind-address}} defaults to the value of {{server-bind-address}} (see below).
46
47Both {{ssl-keyfile}} and {{ssl-pemfile}} ''must'' be provided if you
48want the server to be a HTTPS server.  Don't forget to set the port to 443!
49
50=== Configuration parameters
51
52The following parameters can be used to control spiffy's behaviour.
53Besides these parameters, you can also influence spiffy's behaviour by
54tweaking the [[intarweb]] parameters.
55
56<parameter>(server-software [product])</parameter>
57
58The server software product description. This should be a valid
59product value as used in the server and user-agent headers by intarweb;
60this is a list of lists. The inner lists contain the product name,
61the product version and a comment, all either a string or {{#f}}.
62Default: {{(("Spiffy" "a.b" "Running on Chicken x.y"))}}, with {{a.b}}
63being the Spiffy major/minor version and {{x.y}} being Chicken's.
64
65<parameter>(root-path [path])</parameter>
66
67The path to the document root, for the current vhost.
68Defaults to {{"./web"}}.
69
70<parameter>(server-port [port-number])</parameter>
71
72The port number on which to listen. Defaults to 8080.
73
74<parameter>(server-ssl-pemfile [filename])</parameter>
75
76The SSL "certificate chain" file containing the concatenated
77SSL certificate and key.  This is generally called a "PEM" file.
78
79If this is set to a string and {{server-ssl-keyfile}} is also set,
80this will switch spiffy to HTTPS mode.
81
82If you've set {{spiffy-user}}, this file will be read before dropping
83privileges so you can secure it by making it readable for root only.
84
85Defaults to {{#f}}.
86
87<parameter>(server-ssl-keyfile [filename])</parameter>
88
89The SSL key file.
90
91If this is set to a string and {{server-ssl-pemfile}} is also set,
92this will switch spiffy to HTTPS mode.
93
94If you've set {{spiffy-user}}, this file will be read before dropping
95privileges so you can secure it by making it readable for root only.
96
97Defaults to {{#f}}.
98
99<parameter>(server-ssl-client-context [context])</parameter>
100
101The SSL "client context".  See [[openssl]] for more info.
102Defaults to {{'sslv2-or-v3}}.
103
104<parameter>(server-bind-address [address])</parameter>
105
106The IP address on which to listen, or all addresses if {{#f}}.
107Defaults to {{#f}}.
108
109<parameter>(max-connections [number])</parameter>
110
111The maximum number of simultaneously active connections. Defaults to 1024.
112
113Any new connection that comes in when this number is reached must wait
114until one of the active connections is closed.
115
116<parameter>(spiffy-user [name-or-uid])</parameter>
117
118The name or UID of a user to switch to just after binding the
119port. This only works if you start Spiffy as root, so it can bind port
12080 and then drop privileges. If {{#f}}, no switch will occur.
121Defaults to {{#f}}.
122
123<parameter>(spiffy-group [name-or-gid])</parameter>
124
125The name or GID of a group to switch to just after binding the
126port. This only works if you start Spiffy as root, so it can bind port
12780 and then drop privileges. If {{#f}}, it will be set to the primary
128group of {{spiffy-user}} if the user was selected. Otherwise, no
129change will occur.  Defaults to {{#f}}.
130
131<parameter>(index-files [file-list])</parameter>
132
133A list of filenames which are to be used as index files to serve when
134the requested URL identifies a directory.  Defaults to
135{{'("index.html" "index.xhtml")}}
136
137<parameter>(mime-type-map [extension->mimetype-list])</parameter>
138
139An alist of extensions (strings) to mime-types (symbols), to use
140for the content-type header when serving up a static file. Defaults to
141
142  '(("html" . text/html)
143    ("xhtml" . application/xhtml+xml)
144    ("js"  . application/javascript)
145    ("css" . text/css)
146    ("png" . image/png)
147    ("xml" . application/xml)
148    ("pdf" . application/pdf)
149    ("jpeg" . image/jpeg)
150    ("jpg" . image/jpeg)
151    ("gif" . image/gif)
152    ("ico" . image/vnd.microsoft.icon)
153    ("txt" . text/plain))
154
155See also {{file-extension->mime-type}} for a procedure which
156can look up file extensions for you.
157
158<parameter>(default-mime-type [mime-type])</parameter>
159
160The mime-type (a symbol) to use if none was found in the
161{{mime-type-map}}. Defaults to {{'application/octet-stream}}
162
163<parameter>(default-host [hostname])</parameter>
164
165The host name to use when no virtual host could be determined from the
166request.  See the section on virtual hosts below.
167
168<parameter>(vhost-map [host-regex->vhost-handler])</parameter>
169
170A mapping of virtual hosts (regex) to handlers (procedures of one
171argument; a continuation thunk). See the section on virtual hosts
172below. Defaults to {{`((".*" . ,(lambda (continue) (continue))))}}
173
174<parameter>(file-extension-handlers [extension->handler-list])</parameter>
175
176An alist mapping file extensions (strings) to handler procedures
177(lambdas of one argument; the file name relative to the webroot).
178Defaults to {{'()}}. If no handler was found, defaults to just sending
179a static file.
180
181<parameter>(access-log [log-file-or-port])</parameter>
182
183Filename (string) or port to append access log output to.  Default:
184{{#f}} (disabled)
185
186<parameter>(error-log [log-file-or-port])</parameter>
187
188Filename (string) or port to which error messages from evaluated code
189should be output. Default: {{(current-error-port)}}
190
191<parameter>(debug-log [log-file-or-port])</parameter>
192
193Filename (string) or port to write debugging messages to.  Default:
194{{#f}} (disabled)
195
196<parameter>(access-file [string])</parameter>
197
198The name of an access file, or {{#f}} if not applicable.  This file is
199read when the directory is entered by the directory traversal system,
200and allows you to write dynamic handlers that can assign new values
201for parameters only for resources below that directory, very much like
202adding parameters in code before calling a procedure.  See the section
203"Access files" for more information.
204
205=== Handlers
206
207Besides "static" configuration, Spiffy also has several handlers for
208when something is to be served.
209
210<parameter>(handle-directory [proc])</parameter>
211
212The handler for directory entries. If the requested URL points to a
213directory which has no index file, this handler is invoked. It is a
214procedure of one argument, the path (a string) relative to the
215webroot. Defaults to a procedure which returns a "403 forbidden".
216
217<parameter>(handle-file [proc])</parameter>
218
219The handler for files. If the requested URL points to a file, this
220handler is invoked to serve the file. It is a procedure of one
221argument, the path (a string) relative to the webroot. Defaults to a
222procedure which sets the content-type and determines a handler based
223on the {{file-extension-handlers}}, or {{send-static-file}} if none
224was found.
225
226<parameter>(handle-not-found [proc])</parameter>
227
228The handler for nonexisting files. If the requested URL does not point
229to an existing file or directory, this procedure is called. It is a
230procedure of one argument, the path (a string) that was
231requested. This path should be interpreted as being relative to the
232webroot (even though it points to no existing file). Defaults to a
233procedure which returns a "404 Not found".
234
235<parameter>(handle-exception [proc])</parameter>
236
237The handler for when an exception occurs. This defaults to a procedure
238that logs the error to the error log. While debugging or developing, it
239may be more convenient to use a procedure that sends the error back to
240the client:
241
242<enscript highlight=scheme>
243(handle-exception
244  (lambda (exn chain)
245    (send-status 500 "Internal server error" (build-error-message exn chain))))
246</enscript>
247
248<parameter>(handle-access-logging [proc])</parameter>
249
250The handler for access logging. This is a procedure of zero arguments
251which should write a line to the access log. Defaults to a procedure which
252writes a line to {{access-log}} which looks like this:
253
254   127.0.0.1 [Sun Nov 16 15:16:01 2008] "GET http://localhost:8080/foo?bar HTTP/1.1" 200 "http://localhost:8080/referer" "Links (2.2; NetBSD 5.99.01 macppc; x)"
255
256=== Runtime information
257
258During the handling of a request, Spiffy adds more information to the
259environment by parameterizing the following parameters whenever the
260information becomes available:
261
262<parameter>(current-request [request])</parameter>
263
264An intarweb request-object that defines the current request. Available
265from the moment the request comes in and is parsed. Contains, among
266other things, the query parameters and the request-headers, in fully
267parsed form (as intarweb returns them).
268
269The URI is automatically augmented with the host, scheme and port if
270it is not an absolute URI.
271
272<parameter>(current-response [response])</parameter>
273
274An intarweb response-object that defines the current
275response. Available from the same time current-request is available.
276This keeps getting updated along the way, while the response data is
277being refined (like when headers are being added).
278
279<parameter>(current-file [path])</parameter>
280
281The path to the requested file (a string). Available from the moment
282Spiffy determined the requested URL points to a file (just before the
283{{handle-file}} procedure is called). This file is relative to the
284{{root-path}}.
285
286<parameter>(current-pathinfo [path])</parameter>
287
288The trailing path ''fragments'' (a list of strings) that were passed
289in the URL after the requested filename. Available from the moment
290Spiffy determined the requested URL points to a file (just before the
291{{handle-file}} procedure is called).
292
293<parameter>(remote-address [address])</parameter>
294
295The IP address (a string) of the user-agent performing the current
296request.
297
298<parameter>(local-address [address])</parameter>
299
300The IP address (a string) on which the current request came in.
301
302<parameter>(secure-connection? [boolean])</parameter>
303
304{{#t}} when the current connection is a secure one (SSL), {{#f}} if it
305isn't (regular HTTP).  This pertains only to the direct connection
306itself, so if Spiffy is behind a proxy this will be {{#f}} even if the
307proxy itself is connected to the client over SSL.
308
309=== Virtual hosts
310
311Spiffy has support for virtual hosting, using the HTTP/1.1 Host
312header.  This allows you to use one Spiffy instance running on one IP
313address/port number to serve multiple webpages, as determined by the
314hostname that was requested.
315
316The virtual host is defined by a procedure, which can set arbitrary
317parameters on-the-fly. It is passed a continuation thunk, which it
318should explicitly call if it wants the processing to continue.  The
319most used parameter in virtual host setups is the {{root-path}}
320parameter, so that another docroot can be selected based on the
321requested hostname, showing different websites for different hosts:
322
323<enscript highlight="scheme">
324(vhost-map `(("foo\\.bar\\.com" .
325               ,(lambda (continue)
326                  (parameterize ((file-extension-handlers
327                                   `(("ssp" . ,ssp-handler) ("ws" . ,web-scheme-handler)))
328                                 (root-path "/var/www/domains/foo.bar.com"))
329                     (continue))))
330             (,(glob->regexp "*.domain.com") .
331                ,(lambda (continue)
332                   (parameterize ((file-extension-handlers
333                                    `(("php" . ,(cgi-handler* "/usr/pkg/libexec/cgi-bin/php"))))
334                                  ;; You can also change PHP's arg_separator.input
335                                  ;; to be ";&" instead of this parameter
336                                  (form-urlencoded-separator "&")
337                                  (root-path "/var/www/domains/domain.com"))
338                     (continue))))))
339</enscript>
340
341In this example, if a client accesses
342{{foo.bar.com/mumble/blah.html}}, the file
343{{/var/www/domains/foo.bar.com/mumble/blah.html}} will be served.  Any
344files ending in {{.ssp}} or {{.ws}} will be served by the
345corresponding file type handler.  If there's any PHP file, its source
346will simply be displayed.  In case of
347{{my.domain.com/something/bar.html}}, the file
348{{/var/www/domains/domain.com/something/bar.html}} will be served.  If
349there's a {{.ssp}} or {{.ws}} file there, it will not be interpreted.
350Its source will be displayed instead.  A {{.php}} file, on the other
351hand, will be passed via CGI to the program {{/usr/pkg/bin/php}}.
352
353Domain names are mapped to a lambda that sets up any parameters it
354wants to override from the defaults.  The host names are matched using
355{{string-match}}.  If the host name is not yet a regexp, it will be
356converted to a ''case-insensitive'' regexp.
357
358=== Access files
359
360Fine-grained access-control can be implemented by using so-called
361access files.  When a request for a specific file is made and a file
362with the name given in the {{access-file}} parameter exists in any
363directory between the {{root-path}} of that vhost and the directory in
364which the file resides, then the access file is loaded as an
365s-expression containing a function and is evaluated with a single
366argument, the function that should be called to continue processing
367the request.
368
369This works just like vhosting.  The function that gets called can call
370{{parameterize}} to set additional constraints on the code that
371handles deeper directories.
372
373For example, if we evaluate {{(access-file ".access")}} before
374starting the server, and we put the following code in a file named
375{{.access}} into the root-directory, then all accesses to any file
376in the root-directory or any subdirectory will be denied unless the
377request comes from localhost:
378
379<enscript highlight=scheme>
380 (lambda (continue)
381   (if (string=? (remote-address) "127.0.0.1")
382       (continue)
383       (send-status 403 "Forbidden" "Sorry, you're not allowed here")))
384</enscript>
385
386If we only want to deny access to files that start with an X, put this
387in the {{.access}} file:
388
389<enscript highlight=scheme>
390 (lambda (continue)
391   (let ((old-handler (handle-file)))
392     (parameterize ((handle-file
393                      (lambda (path)
394                        (if (not (string-prefix? "X" (pathname-file path)))
395                            (send-status 403 "Forbidden" "No X-files allowed!")
396                            (old-handler path)))))
397       (continue))))
398</enscript>
399
400Of course, access files can be used for much more than just access
401checks.  One can put anything in them that could be put in vhost
402configuration or in top-level configuration.
403
404They are very useful for making deployable web applications, so you
405can just drop a directory on your server which has its own
406configuration embedded in an access file in the root directory of the
407application, without having to edit the server's main configuration
408files.
409
410=== Procedures and macros
411
412The following procedures and macros can be used in dynamic web
413programs, or dynamic server configuration:
414
415<procedure>(with-headers new-headers thunk)</procedure>
416
417Call {{thunk}} with the header list {{new-headers}}. This
418parameterizes the current response to contain the new headers.  The
419existing headers are extended with {{new-headers}} through intarweb's
420{{headers}} procedure.
421
422<procedure>(write-logged-response)</procedure>
423
424This procedure simply writes {{current-response}} after calling
425{{handle-access-logging}}. Responses should always go through this
426procedure instead of directly using {{write-response}} from intarweb.
427
428<procedure>(log-to log format . rest)</procedure>
429
430Write a printf-style format string to the specified log (one of
431{{access-log}}, {{error-log}} or {{debug-log}}). {{format}} is a
432{{printf}}-style format string, and rest arguments should match
433the arguments one would pass to printf. A newline is appended to
434the end of the log message automatically.
435
436<procedure>(send-response #!key (code 200) (reason "OK") body (headers '()))</procedure>
437
438Easy way to send string data to the client, with additional headers.
439It will add appropriate headers and will automatically detect {{HEAD}}
440requests.  If BODY is {{#f}}, no body is sent and the {{content-length}}
441header is set to zero.
442
443<procedure>(send-status code reason [message])</procedure>
444
445Easy way to send a page and a status code to the client.  The optional
446message is a string containing HTML to add in the body of the
447response. Some structure will be added around the message, so message
448should only be the actual message you want to send.  Example:
449
450<enscript highight="scheme">
451(send-status 404 "Not found"
452 "Sorry, page not found! Please try <a href='/search.ws'>our search page</a>")
453</enscript>
454
455<procedure>(send-static-file filename)</procedure>
456
457Send a file to the client. This sets the {{content-length}} header and
458tries to send the file as quickly as possible to the client. The
459filename is interpreted relative to {{root-path}}.
460
461<procedure>(file-extension->mime-type EXT)</procedure>
462
463Looks up the file extension {{EXT}} (without a trailing dot)
464in {{mime-type-map}}, or uses {{default-mime-type}} when the
465extension can't be found.
466
467If {{EXT}} is {{#f}}, it'll look up the extension that is the
468empty string.
469
470This returns a symbol which indicates the mime-type which is matched
471to the extension (for example {{text/html}}).
472
473<procedure>(restart-request request)</procedure>
474
475Restart the entire request-handling starting at the point where the
476request was just parsed. The argument is the new request to use.
477Be careful, this makes it very easy to introduce unwanted endless loops!
478
479<procedure>(htmlize string) => string</procedure>
480
481Encode "special" html symbols like tag and attribute characters so
482they will not be interpreted by the browser.
483
484<procedure>(build-error-message exn chain [raw-output])</procedure>
485
486Build an error message for the exception {{exn}}, with call chain
487{{chain}}. Defaults to HTML output, unless {{raw-output}} is given and
488nonfalse.
489
490=== Modules
491
492This section will describe what the various modules that come with
493Spiffy are and how they work.
494
495==== ssp-handler
496
497SSP, or Scheme Server Pages, are a way to embed Scheme in HTML
498pages. Files with an extension of {{.ssp}} are handled specifically,
499by replacing occurrences of certain reserved tags with Scheme code.
500There are two possible forms, either the long version, where all
501output is redirected to the HTTP response port, or the short, where
502the result of the embedded expression is displayed in the response.
503The tags default to {{<?scheme}} and {{<?}}, see Configuration for how
504to change them.
505
506<enscript highlight=scheme>
507   <html><body>
508   <ol><?scheme (for-each (lambda (i) (printf "<li>~S~%" i)) (iota 5))?></ol>
509   <br />
510   <b><?(call-with-values (lambda () (user-information (current-user-id))) (lambda (name . _) name))?><b>
511   </body></html>
512</enscript>
513
514would generate for example something like this:
515
516     1. 0
517     2. 1
518     3. 2
519     4. 3
520     5. 4
521
522  (felix x 500 100 /home/felix /bin/bash)
523
524When a {{.ssp}} file is loaded the first time, or when it has been
525modified, then a translation takes place that generates a loadable
526Scheme source file (with the extension {{.sspx}}, in the same
527directory as the original file) from the original data, so in the
528above example something like this would be generated:
529
530<enscript highlight=scheme>
531  (let ()
532    (display "<html><body>\n<ol>")
533    (for-each (lambda (i) (printf "<li>~S~%" i)) (iota 5))
534    (display "</ol>\n<br />\n<b>")
535    (display (call-with-values (lambda () (user-information (current-user-id))) (lambda (name . _) name)))
536    (display "<b>\n</body></html>\n") )
537</enscript>
538
539Note that the body is evaluated in a {{(let () ...)}} form.
540
541Note: each request runs in a separate thread, so code in {{.ssp}}
542pages should take care when using global variables.
543
544===== Configuration
545
546The SSP handler can be configured with the following options:
547
548<parameter>(ssp-short-open-tag [tag-regexp])</parameter>
549
550The opening tag for short fragments. Default: {{<?}}
551
552<parameter>(ssp-long-open-tag [tag-regexp])</parameter>
553
554The opening tag for long fragments. Default: {{<?scheme}}
555
556<parameter>(ssp-close-tag [tag-regexp])</parameter>
557
558The closing tag for Scheme fragments in {{.ssp}} files. Default: {{?>}}
559
560<parameter>(ssp-eval-environment [environment])</parameter>
561
562The environment passed to {{eval}} when evaluating Scheme code inside
563{{.ssp}}-pages.  Default: {{interaction-environment}}
564
565<parameter>(ssp-cache-dir [directory-name])</parameter>
566
567The directory under which to store cached .ssp files (these end in .sspx
568and are pure Scheme files).  Useful if you want to block write access to
569the webserver under your docroot.  Default: {{"."}}
570
571If it's a relative path, it is relative to {{root-path}}, if absolute
572it's taken to be relative to the filesystem root.  A directory structure
573similar to the docroot will be created underneath this path, so for
574example if the file {{/foo/bar/qux.ssp}} exists, and the cache dir is
575set to {{/cache}}, it will create the file {{/cache/foo/bar/qux.sspx}}.
576
577===== Runtime information
578
579For the duration of evaluating a SSP page, the following parameters
580will have a value assigned to them:
581
582<parameter>(current-workdir [path])</parameter>
583
584During execution, the current working directory of the SSP handler.
585Any of the "include" procedures (ssp-include, ssp-stringize) will
586interpret their file arguments to be relative to this directory.
587
588<parameter>(ssp-exit-handler [handler])</parameter>
589
590During execution of an ssp page, {{ssp-exit-handler}} is bound to a
591procedure that will finish the current page, ignoring any further
592content or code.
593
594===== Procedures
595
596The ssp-handler module adds the following procedures to the environment:
597
598<procedure>(ssp-handler filename)</procedure>
599
600The handler itself, which should be used in the {{file-extension-handlers}}
601parameter list.
602
603<procedure>(ssp-include filename)</procedure>
604
605Translates the file {{filename}} into Scheme by replacing {{<?scheme ... ?>}}
606and {{<? ... ?>}} sequences (if needed) and writes the translated contents
607to the current output-port.
608
609<procedure>(ssp-stringize FILENAME)</procedure>
610
611Similar to {{ssp-include}}, but instead of writing the translated
612text, the text is returned as a string.
613
614==== web-scheme-handler
615
616Another way of executing Scheme code to produce content are {{.ws}}
617files: these should contain a Scheme expression that is expected to
618evaluate to a string which will be directly written as the response to
619the current request. This facility is intended for Scheme code that
620uses the [[web-scheme]] extension.
621
622You can use the {{web-scheme-handler}} for any Scheme file which
623returns HTML as a string or which has a side-effect of outputting the
624HTML. If it's the latter, make sure the final statement in your file
625does not return a string or it will be appended to the output (just
626like in the {{csi}} REPL).
627
628'''Tip''' This handler type is perfect not only for web-scheme but
629also for when you're using {{SRV:send-reply}} with SXML or for example a
630wiki-to-string translator.
631
632Note: each request runs in a separate thread, so code in {{.ws}} pages
633should take care when using global variables.
634
635Note: web-scheme-handler is a separate extension and must be imported
636as such.
637
638<enscript highlight=scheme>
639(require-extension web-scheme-handler)
640</enscript>
641
642===== Configuration
643
644The Web-scheme handler can be configured with the following options:
645
646<parameter>(web-scheme-eval-environment [environment])</parameter>
647
648The environment passed to {{eval}} when evaluating Scheme code inside
649{{.ws}}-pages.  Default: {{interaction-environment}}
650
651===== Procedures
652
653The Web-scheme handler adds only one procedure to the environment:
654
655<procedure>(web-scheme-handler filename)</procedure>
656
657The handler itself, which should be used in the {{file-extension-handlers}}
658parameter list.
659
660
661==== cgi-handler
662
663Spiffy supports [[http://www.ietf.org/rfc/rfc3875|CGI/1.1 as specified by RFC 3875]].
664
665All request headers will be passed as environment variables to the CGI
666program, prefixed with {{"HTTP_"}}, and converted to uppercase, with
667hyphens ("-") replaced by an underscore ("_"). The CGI program will
668receive the request body in unparsed form from stdin and should write
669a complete HTTP response to stdout.  Any headers that are missing but
670required for HTTP will be added by Spiffy.  For more info on how a CGI
671script is called, consult the spec.
672
673The {{AUTH_TYPE}} and {{REMOTE_USER}} environment variables are
674currently not set during invocation of CGI subprocesses.
675The {{REMOTE_IDENT}} environment variable is not and never will be supported.
676
677===== Configuration
678
679CGI handler can be configured with the following parameters:
680
681<procedure>(cgi-default-environment [env-alist])</procedure>
682
683The environment variables that should be in the default environnment
684of every CGI program.  Variables like {{SCRIPT_NAME}} will be added
685dynamically to the end of this alist.
686
687Default:
688
689<enscript highlight=scheme>
690(("GATEWAY_INTERFACE" . "CGI/1.1"))
691</enscript>
692
693===== Procedures
694
695CGI-handler adds two procedures to the environment:
696
697<procedure>(cgi-handler filename [interpreter])</procedure>
698
699The cgi handler simply calls CGI scripts. It is assumed the
700requested file is executable if no interpreter is given.
701(If used as a regular handler, it will only receive the
702filename).  The filename is taken to be relative to {{(root-path)}}.
703
704<procedure>(cgi-handler* [interpreter])</procedure>
705
706The {{cgi-handler*}} procedure is usually more useful.  It allows you
707to define an interpreter to use for files and returns a new handler.
708See the example above for {{file-extension-handlers}}.
709
710
711==== simple-directory-handler
712
713In order to get directory listings, you can use
714{{simple-directory-handler}}.  Just assign the
715{{simple-directory-handler}} to {{handle-directory}} and you're set.
716
717===== Configuration
718
719The simple directory handler has a few configuration options:
720
721<procedure>(simple-directory-dotfiles? [dotfiles?])</procedure>
722
723Determines if dotfiles should show up in the directory listings.
724Default: {{#f}}
725
726<procedure>(simple-directory-display-file [displayer])</procedure>
727
728A lambda that accepts three arguments: the remote filename, the local
729filename and a boolean that says if the file is a directory.  This
730lambda should output a table row with the desired information.
731Defaults to a lambda that prints the name, size and date when the file
732was last modified.
733
734===== Procedures
735
736The simple-directory handler adds only one procedure to the environment:
737
738<procedure>(simple-directory-handler pathname)</procedure>
739
740The handler itself, which should be used in the {{handle-directory}}
741parameter.
742
743=== Examples
744
745Spiffy is very easy to use for simple cases:
746
747<enscript highlight=scheme>
748(use spiffy)
749
750(server-port 80)
751(root-path "/var/www")
752(start-server)
753</enscript>
754
755One could also use parameterize:
756
757<enscript highlight=scheme>
758(use spiffy)
759
760(parameterize ((server-port 80)
761               (root-path "/var/www"))
762  (start-server))
763</enscript>
764
765==== Network tweaks
766
767Spiffy does not activate Chicken's TCP buffering, which results in
768extra traffic: one packet sent per header line.  With a TCP buffer
769size greater than the total header length, all headers will be
770coalesced into a single write; generally the response body will be
771coalesced as well.  For example:
772
773 (tcp-buffer-size 2048)   ; from unit tcp
774 (start-server)
775
776=== Changelog
777
778* 4.9 Export {{file-extension->mime-type}}. Add more info about exceptional situations to the debugging logs when enabled.
779* 4.8 Fix ssl support. Get rid of {{spiffy-root-uri}}. Add timestamp and request info to error log.
780* 4.7 Fix redirects for directories again (thanks to [[/users/mario-domenech-goulart|Mario]]). NO TESTCASE (possibly to be fixed in [[uri-generic]])
781* 4.6 Fix redirects for directories with special URI characters in them (thanks to [[/users/felix-winkelmann|Felix]])
782* 4.5 Add {{send-response}} procedure; flush output after request is handled; use proper IANA-assigned MIME types in default {{mime-type-map}}; fix {{server-root-uri}} when spiffy is behind a proxy [thanks to zbigniew]
783* 4.4 Fix a problem with 304 "not modified", for which Safari incorrectly tries to read a content-body when a content-length is present.
784* 4.3 Fix crash with extensionless files and nonempty extension handlers
785* 4.2 Add support for caching headers and proper If-Modified-Since support
786* 4.1 Make cgi-handler cope with missing pathinfo. Fix statuscode related crash in cgi-handler. Make ssp handler's open/close tags parameters, so it actually matches what the documentation says. Add {{ssp-cache-dir}}. Update for latest intarweb changes (0.2)
787* 4.0 Rewrite from scratch, using Intarweb
788* pre-4.0 See the changelog for the [[/eggref/3/spiffy|old spiffy]]
789
790=== License
791
792  Copyright (c) 2005-2010, Felix L. Winkelmann and Peter Bex
793  All rights reserved.
794 
795  Redistribution and use in source and binary forms, with or without
796  modification, are permitted provided that the following conditions are
797  met:
798 
799  Redistributions of source code must retain the above copyright
800  notice, this list of conditions and the following disclaimer.
801 
802  Redistributions in binary form must reproduce the above copyright
803  notice, this list of conditions and the following disclaimer in the
804  documentation and/or other materials provided with the distribution.
805 
806  Neither the name of the author nor the names of its contributors may
807  be used to endorse or promote products derived from this software
808  without specific prior written permission.
809 
810  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
811  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
812  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
813  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
814  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
815  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
816  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
817  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
818  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
819  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
820  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
821  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.