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