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

Last change on this file since 12530 was 12530, checked in by sjamaan, 12 years ago

Add server-software parameter to docs

File size: 20.5 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[[Felix Winkelmann]].  Currently maintained by [[Peter Bex]].
14
15=== Requirements
16
17Requires the [[intarweb]], [[matchable]] and [[sendfile]] extensions.
18
19=== Download
20
21[[http://www.call-with-current-continuation.org/eggs/spiffy.egg|spiffy.egg]]
22
23=== Documentation
24
25Spiffy is a web-server library for the Chicken Scheme system. It's
26quite easy to set up and use (whether as a library or a standalone
27server application) and it can be customized in numerous ways.
28
29=== Starting the server
30
31<procedure>(start-server [port: port-number])</procedure>
32
33Starts the server, to listen on the given port. Other configuration
34can be tweaked through SRFI-39 parameters. These are listed below.
35Once the server is started, server behaviour can be controlled through
36these parameters as well. By default, Spiffy will only serve static
37files. On directories, it will give a "403 forbidden", unless there
38is an index-file. If there is, that file's contents will be shown.
39
40All arguments directly supplied to {{start-server}} override the
41configuration parameter values.
42
43{{Port-number}} defaults to the value of {{server-port}} (see below).
44
45=== Configuration parameters
46
47The following parameters can be used to control spiffy's behaviour.
48Besides these parameters, you can also influence spiffy's behaviour by
49tweaking the [[intarweb]] parameters.
50
51<parameter>(server-software [product])</parameter>
52
53The server software product description. This should be a valid
54product value as used in the server and user-agent headers by intarweb;
55this is a list of lists. The inner lists contain the product name,
56the product version and a comment, all either a string or {{#f}}.
57Default: {{(("Spiffy" "a.b" "Running on Chicken x.y"))}}, with {{a.b}}
58being the Spiffy major/minor version and {{x.y}} being Chicken's.
59
60<parameter>(root-path [path])</parameter>
61
62The path to the document root. Defaults to {{"./web"}}.
63
64<parameter>(server-port [port-number])</parameter>
65
66The port number on which to listen. Defaults to 8080.
67
68<parameter>(index-files [file-list])</parameter>
69
70A list of filenames which are to be used as index files to serve when
71the requested URL identifies a directory.  Defaults to
72{{'("index.html" "index.xhtml")}}
73
74<parameter>(mime-type-map [extension->mimetype-list])</parameter>
75
76An alist of extensions (strings) to mime-types (symbols), to use
77for the content-type header when serving up a static file. Defaults to
78  (("xml" . text/xml)
79   ("html" . text/html)
80   ("xhtml" . text/xhtml+xml)
81   ("js"  . text/javascript)
82   ("pdf" . application/pdf)
83   ("css" . text/css)
84   ("png" . image/png)
85   ("ico" . image/x-icon)
86   ("gif" . image/gif)
87   ("jpeg" . image/jpeg)
88   ("jpg" . image/jpeg)
89   ("svg" . image/svg+xml)
90   ("bmp" . image/bmp)
91   ("txt" . text/plain))
92
93<parameter>(default-mime-type [mime-type])</parameter>
94
95The mime-type (a symbol) to use if none was found in the
96{{mime-type-map}}. Defaults to {{'application/octet-stream}}
97
98<parameter>(default-host [hostname])</parameter>
99
100The host name to use when no virtual host could be determined from the
101request.  See the section on virtual hosts below.
102
103<parameter>(vhost-map [host-regex->vhost-handler])</parameter>
104
105A mapping of virtual hosts (regex) to handlers (procedures of one
106argument; a continuation thunk). See the section on virtual hosts
107below. Defaults to {{`((".*" . ,(lambda (continue) (continue))))}}
108
109<parameter>(file-extension-handlers [extension->handler-list])</parameter>
110
111An alist mapping file extensions (strings) to handler procedures
112(lambdas of one argument; the file name relative to the webroot).
113Defaults to {{'()}}. If no handler was found, defaults to just sending
114a static file.
115
116<parameter>(spiffy-access-log [log-file-or-port])</parameter>
117
118Filename (string) or port to append access log output to.  Default:
119{{#f}} (disabled)
120
121<parameter>(spiffy-error-log [log-file-or-port])</parameter>
122
123Filename (string) or port to which error messages from evaluated code
124should be output. Default: {{(current-error-port)}}
125
126<parameter>(spiffy-debug-log [log-file-or-port])</parameter>
127
128Filename (string) or port to write debugging messages to.  Default:
129{{#f}} (disabled)
130
131
132=== Handlers
133
134Besides "static" configuration, Spiffy also has several handlers for
135when something is to be served.
136
137<parameter>(handle-directory [proc])</parameter>
138
139The handler for directory entries. If the requested URL points to a
140directory which has no index file, this handler is invoked. It is a
141procedure of one argument, the path (a string) relative to the
142webroot. Defaults to a procedure which returns a "403 forbidden".
143
144<parameter>(handle-file [proc])</parameter>
145
146The handler for files. If the requested URL points to a file, this
147handler is invoked to serve the file. It is a procedure of one
148argument, the path (a string) relative to the webroot. Defaults to a
149procedure which sets the content-type and determines a handler based
150on the {{file-extension-handlers}}, or {{send-static-file}} if none
151was found.
152
153<parameter>(handle-not-found [proc])</parameter>
154
155The handler for nonexisting files. If the requested URL does not point
156to an existing file or directory, this procedure is called. It is a
157procedure of one argument, the path (a string) that was
158requested. This path should be interpreted as being relative to the
159webroot (even though it points to no existing file). Defaults to a
160procedure which returns a "404 Not found".
161
162<parameter>(handle-access-logging [proc])</parameter>
163
164The handler for access logging. This is a procedure of zero arguments
165which should write a line to the access log. Defaults to a procedure which
166writes a line to {{access-log}} which looks like this:
167
168   127.0.0.1 [Sun Nov 16 15:16:01 2008] "GET http://localhost:8080/foo HTTP/1.1" Links (2.2; NetBSD 5.99.01 macppc; x)
169
170=== Runtime information
171
172During the handling of a request, Spiffy adds more information to the
173environment by parameterizing the following parameters whenever the
174information becomes available:
175
176<parameter>(current-request [request])</parameter>
177
178An intarweb request-object that defines the current request. Available
179from the moment the request comes in and is parsed. Contains, among
180other things, the query parameters and the request-headers, in fully
181parsed form (as intarweb returns them).
182
183<parameter>(current-response [request])</parameter>
184
185An intarweb response-object that defines the current
186response. Available from the same time current-request is available.
187This keeps getting updated along the way, while the response data is
188being refined (like when headers are being added).
189
190<parameter>(current-file [path])</parameter>
191
192The path to the requested file (a string). Available from the moment
193Spiffy determined the requested URL points to a file (just before the
194{{handle-file}} procedure is called).
195
196<parameter>(current-pathinfo [path])</parameter>
197
198The trailing path ''fragments'' (a list of strings) that were passed
199in the URL after the requested filename. Available from the moment
200Spiffy determined the requested URL points to a file (just before the
201{{handle-file}} procedure is called).
202
203=== Virtual hosts
204
205Spiffy has support for virtual hosting, using the HTTP/1.1 Host
206header.  This allows you to use one Spiffy instance running on one IP
207address/port number to serve multiple webpages, as determined by the
208hostname that was requested.
209
210The virtual host is defined by a procedure, which can set arbitrary
211parameters on-the-fly. It is passed a continuation thunk, which it
212should explicitly call if it wants the processing to continue.  The
213most used parameter in virtual host setups is the {{root-path}}
214parameter, so that another docroot can be selected based on the
215requested hostname, showing different websites for different hosts:
216
217<example>
218<expr>
219(vhost-map `(("foo\\.bar\\.com" .
220               ,(lambda (continue)
221                  (parameterize ((file-extension-handlers
222                                   `(("ssp" . ,ssp-handler) ("ws" . ,web-scheme-handler)))
223                                 (root-path "/var/www/domains/foo.bar.com"))
224                     (continue))))
225             (,(glob->regexp "*.domain.com") .
226                ,(lambda (continue)
227                   (parameterize ((file-extension-handlers
228                                    `(("php" . ,(cgi-handler* "/usr/pkg/bin/php"))))
229                                  (root-path "/var/www/domains/domain.com"))
230                     (continue))))))
231</expr>
232</example>
233
234In this example, if a client accesses
235{{foo.bar.com/mumble/blah.html}}, the file
236{{/var/www/domains/foo.bar.com/mumble/blah.html}} will be served.  Any
237files ending in {{.ssp}} or {{.ws}} will be served by the
238corresponding file type handler.  If there's any PHP file, its source
239will simply be displayed.  In case of
240{{my.domain.com/something/bar.html}}, the file
241{{/var/www/domains/domain.com/something/bar.html}} will be served.  If
242there's a {{.ssp}} or {{.ws}} file there, it will not be interpreted.
243Its source will be displayed instead.  A {{.php}} file, on the other
244hand, will be passed via CGI to the program {{/usr/pkg/bin/php}}.
245
246Domain names are mapped to a lambda that sets up any parameters it
247wants to override from the defaults.  The host names are matched using
248{{string-match}}.  If the host name is not yet a regexp, it will be
249converted to a ''case-insensitive'' regexp.
250
251=== Procedures and macros
252
253The following procedures and macros can be used in dynamic web
254programs, or dynamic server configuration:
255
256<procedure>(with-headers new-headers thunk)</procedure>
257
258Call {{thunk}} with the header list {{new-headers}}. This
259parameterizes the current response to contain the new headers.  The
260existing headers are extended with {{new-headers}} through intarweb's
261{{headers}} procedure.
262
263<procedure>(write-logged-response)</procedure>
264
265This procedure simply writes {{current-response}} after calling
266{{handle-access-logging}}. Responses should always go through this
267procedure instead of directly using {{write-response}} from intarweb.
268
269<procedure>(log-to log format . rest)</procedure>
270
271Write a printf-style format string to the specified log (one of
272{{access-log}}, {{error-log}} or {{debug-log}}). {{format}} is a
273{{printf}}-style format string, and rest arguments should match
274the arguments one would pass to printf. A newline is appended to
275the end of the log message automatically.
276
277<procedure>(send-status code reason [message])</procedure>
278
279Easy way to send a page and a status code to the client.  The optional
280message is a string containing HTML to add in the body of the
281response. Example:
282
283<example>
284<expr>
285(send-status 404 "Not found"
286 "Sorry, page not found! Please try <a href='/search.ws'>our search page</a>")
287</expr>
288</example>
289
290<procedure>(send-static-file filename)</procedure>
291
292Send a file to the client. This sets the {{content-length}} header and
293tries to send the file as quickly as possible to the client. The
294filename is interpreted relative to {{root-path}}.
295
296<procedure>(restart-request request)</procedure>
297
298Restart the entire request-handling starting at the point where the
299request was just parsed. The argument is the new request to use.
300Be careful, this makes it very easy to introduce unwanted endless loops!
301
302=== Modules
303
304This section will describe what the various modules that come with
305Spiffy are and how they work.
306
307==== ssp-handler
308
309SSP, or Scheme Server Pages, are a way to embed Scheme in HTML
310pages. Files with an extension of {{.ssp}} are handled specifically,
311by replacing occurrences of certain reserved tags with Scheme code.
312There are two possible forms, either the long version, where all
313output is redirected to the HTTP response port, or the short, where
314the result of the embedded expression is displayed in the response.
315The tags default to {{<?scheme}} and {{<?}}, see Configuration for how
316to change them.
317
318<enscript highlight=scheme>
319   <html><body>
320   <ol><?scheme (for-each (lambda (i) (printf "<li>~S~%" i)) (iota 5))?></ol>
321   <br />
322   <b><?(call-with-values (lambda () (user-information (current-user-id))) (lambda (name . _) name))?><b>
323   </body></html>
324</enscript>
325
326would generate for example something like this:
327
328     1. 0
329     2. 1
330     3. 2
331     4. 3
332     5. 4
333
334  (felix x 500 100 /home/felix /bin/bash)
335
336When a {{.ssp}} file is loaded the first time, or when it has been
337modified, then a translation takes place that generates a loadable
338Scheme source file (with the extension {{.sspx}}, in the same
339directory as the original file) from the original data, so in the
340above example something like this would be generated:
341
342<enscript highlight=scheme>
343  (let ()
344    (display "<html><body>\n<ol>")
345    (for-each (lambda (i) (printf "<li>~S~%" i)) (iota 5))
346    (display "</ol>\n<br />\n<b>")
347    (display (call-with-values (lambda () (user-information (current-user-id))) (lambda (name . _) name)))
348    (display "<b>\n</body></html>\n") )
349</enscript>
350
351Note that the body is evaluated in a {{(let () ...)}} form.
352
353Note: each request runs in a separate thread, so code in {{.ssp}}
354pages should take care when using global variables.
355
356===== Configuration
357
358The SSP handler can be configured with the following options:
359
360<parameter>(ssp-short-open-tag [tag-regexp])</parameter>
361
362The opening tag for short fragments. Default: {{<?}}
363
364<parameter>(ssp-long-open-tag [tag-regexp])</parameter>
365
366The opening tag for long fragments. Default: {{<?scheme}}
367
368<parameter>(ssp-close-tag [tag-regexp])</parameter>
369
370The closing tag for Scheme fragments in {{.ssp}} files. Default: {{?>}}
371
372<parameter>(ssp-eval-environment [environment])</parameter>
373
374The environment passed to {{eval}} when evaluating Scheme code inside
375{{.ssp}}-pages.  Default: {{interaction-environment}}
376
377===== Runtime information
378
379For the duration of evaluating a SSP page, the following parameters
380will have a value assigned to them:
381
382<parameter>(current-workdir [path])</parameter>
383
384During execution, the current working directory of the SSP handler.
385Any of the "include" procedures (ssp-include, ssp-stringize) will
386interpret their file arguments to be relative to this directory.
387
388<parameter>(ssp-exit-handler [handler])</parameter>
389
390During execution of an ssp page, {{ssp-exit-handler}} is bound to a
391procedure that will finish the current page, ignoring any further
392content or code.
393
394===== Procedures
395
396The ssp-handler module adds the following procedures to the environment:
397
398<procedure>(ssp-handler filename)</procedure>
399
400The handler itself, which should be used in the {{file-extension-handlers}}
401parameter list.
402
403<procedure>(ssp-include filename)</procedure>
404
405Translates the file {{filename}} into Scheme by replacing {{<?scheme ... ?>}}
406and {{<? ... ?>}} sequences (if needed) and writes the translated contents
407to the current output-port.
408
409<procedure>(ssp-stringize FILENAME)</procedure>
410
411Similar to {{ssp-include}}, but instead of writing the translated
412text, the text is returned as a string.
413
414==== web-scheme-handler
415
416Another way of executing Scheme code to produce content are {{.ws}}
417files: these should contain a Scheme expression that is expected to
418evaluate to a string which will be directly written as the response to
419the current request. This facility is intended for Scheme code that
420uses the [[web-scheme]] extension.
421
422You can use the {{web-scheme-handler}} for any Scheme file which
423returns HTML as a string or which has a side-effect of outputting the
424HTML. If it's the latter, make sure the final statement in your file
425does not return a string or it will be appended to the output (just
426like in the {{csi}} REPL).
427
428'''Tip''' This handler type is perfect not only for web-scheme but
429also for when you're using {{SRV:send-reply}} with SXML or for example a
430wiki-to-string translator.
431
432Note: each request runs in a separate thread, so code in {{.ws}} pages
433should take care when using global variables.
434
435Note: web-scheme-handler is a separate extension and must be imported
436as such.
437
438<enscript highlight=scheme>
439(require-extension web-scheme-handler)
440</enscript>
441
442===== Configuration
443
444The Web-scheme handler can be configured with the following options:
445
446<parameter>(web-scheme-eval-environment [environment])</parameter>
447
448The environment passed to {{eval}} when evaluating Scheme code inside
449{{.ws}}-pages.  Default: {{interaction-environment}}
450
451===== Procedures
452
453The Web-scheme handler adds only one procedure to the environment:
454
455<procedure>(web-scheme-handler filename)</procedure>
456
457The handler itself, which should be used in the {{file-extension-handlers}}
458parameter list.
459
460
461==== cgi-handler
462
463Spiffy supports [[http://www.ietf.org/rfc/rfc3875|CGI/1.1 as specified by RFC 3875]].
464
465All request headers will be passed as environment variables to the CGI
466program, prefixed with {{"HTTP_"}}, and converted to uppercase, with
467hyphens ("-") replaced by an underscore ("_"). The CGI program will
468receive the request body in unparsed form from stdin and should write
469a complete HTTP response to stdout.  Any headers that are missing but
470required for HTTP will be added by Spiffy.  For more info on how a CGI
471script is called, consult the spec.
472
473The {{AUTH_TYPE}} and {{REMOTE_USER}} environment variables are
474currently not set during invocation of CGI subprocesses.
475The {{REMOTE_IDENT}} environment variable is not and never will be supported.
476
477===== Configuration
478
479CGI handler can be configured with the following parameters:
480
481<procedure>(cgi-default-environment [env-alist])</procedure>
482
483The environment variables that should be in the default environnment
484of every CGI program.  Variables like {{SCRIPT_NAME}} will be added
485dynamically to the end of this alist.
486
487Default:
488
489<enscript highlight=scheme>
490(("GATEWAY_INTERFACE" . "CGI/1.1"))
491</enscript>
492
493===== Procedures
494
495CGI-handler adds two procedures to the environment:
496
497<procedure>(cgi-handler filename [interpreter])</procedure>
498
499The {{cgi-handler}} procedure is called by {{cgi-handler*}} with the
500filename. It's not very useful on its own.
501
502<procedure>(cgi-handler* [interpreter])</procedure>
503
504The {{cgi-handler*}} procedure is usually more useful.  It allows you
505to define an interpreter to use for files and returns a file handler.
506See the example above for {{file-extension-handlers}}.
507
508
509==== simple-directory-handler
510
511In order to get directory listings, you can use
512{{simple-directory-handler}}.  Just assign the
513{{simple-directory-handler}} to {{handle-directory}} and you're set.
514
515===== Configuration
516
517The simple directory handler has a few configuration options:
518
519<procedure>(simple-directory-dotfiles? [dotfiles?])</procedure>
520
521Determines if dotfiles should show up in the directory listings.
522Default: {{#f}}
523
524<procedure>(simple-directory-display-file [displayer])</procedure>
525
526A lambda that accepts three arguments: the remote filename, the local
527filename and a boolean that says if the file is a directory.  This
528lambda should output a table row with the desired information.
529Defaults to a lambda that prints the name, size and date when the file
530was last modified.
531
532===== Procedures
533
534The simple-directory handler adds only one procedure to the environment:
535
536<procedure>(simple-directory-handler pathname)</procedure>
537
538The handler itself, which should be used in the {{handle-directory}}
539parameter.
540
541
542=== Changelog
543
544* 4.0 Rewrite from scratch, using Intarweb
545* pre-4.0 See the changelog for the old [[spiffy]]
546
547=== License
548
549  Copyright (c) 2005-2008, Felix L. Winkelmann and Peter Bex
550  All rights reserved.
551 
552  Redistribution and use in source and binary forms, with or without
553  modification, are permitted provided that the following conditions are
554  met:
555 
556  Redistributions of source code must retain the above copyright
557  notice, this list of conditions and the following disclaimer.
558 
559  Redistributions in binary form must reproduce the above copyright
560  notice, this list of conditions and the following disclaimer in the
561  documentation and/or other materials provided with the distribution.
562 
563  Neither the name of the author nor the names of its contributors may
564  be used to endorse or promote products derived from this software
565  without specific prior written permission.
566 
567  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
568  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
569  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
570  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
571  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
572  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
573  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
574  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
575  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
576  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
577  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
578  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.