source: project/wiki/eggref/4/uri-dispatch @ 15380

Last change on this file since 15380 was 15380, checked in by certainty, 12 years ago

Changes applied for certainty (82.82.131.238) through svnwiki:

  • Property svnwiki:tags set to web
  • Property svnwiki:title set to uri-dispatch
File size: 4.9 KB
Line 
1=== Description
2
3uri-dispatch is a simple mechanism to dispatch uris to procedures.
4This is useful for webprogramming where you might want to map uris of a certain kind
5to procedures that implement the logic for those uris.
6
7=== Author
8
9[[David Krentzlin]]
10
11=== Requirements
12
13Requires the [[uri-common]] and [[environments]] extensions.
14
15=== Documentation
16
17<procedure>(dispatch-uri URI)</procedure>
18
19The main interface to dispatch-uri. This procedure invokes the dispatch-mechanism with the supplied uri.
20The dispatch-algorithm is implemented as follows:
21
22('''Note''' Although not explicitly stated here the algorithm performs a whitelist-check on any procedure before it is invoked. See '''enable-whitelisting''' and '''whitelist!''')
23
24* The path is empty. It checks if '''default-dispatch-target''' is bound to a procedure.
25   If it is, then it is invoked. If it is not, then '''dispatch-error''' is invoked.
26
27* The path has exactly one element. It assumes that this element is the name
28   of a thunk that was defined outside a module. If such a thunk exists it is invoked.
29   If no such a thunk exists '''dispatch-error'''.is invoked.
30
31* The path contains at least two elements.
32** It checks if the second element is a procedure defined
33  in a module named by the first element. So if it sees (foo bar) it tries to find the procedure foo
34  inside the module bar. If the procedure exists it is invoked with the rest of the elements as arguments.
35** If it does not exist, it interpretes the first element as the name of a procedure that was defined
36  outside any module. If such a procedure exists, it is invoked passing the rest of the elements as arguments.
37  If no such procedure exists '''dispatch-error''' is invoked with the full path as arguments. The path is applied
38  to the procedure so you can use for example dsssl-style lambdalists to declare optional arguments or a rest-argument.
39
40
41<procedure>(whitelist! DEFINITION)</procedure>
42Though nice for development it is not advisable to allow anybody out there to invoke abritary procedures of your application.
43So you might want to '''enable-whitelisting''' in production and whitelist only those modules and/or procedures you really want
44to be callable from the outside. Whis procedure expects a list that defines the procedure/modules
45you want to whitelist. If a procedure is requested that does exist but is not whitelisted '''dispatch-error''' is invoked.
46You have basically two possibilities to perform whitelisting, all of which can be combined.
47
481) whitelist procedures outside modules
49<pre>(whitelist! '(procedure1 procedure2 procedure3))</pre>
50
512) whitelist all procedures inside a module
52<pre>(whitelist! '((module my-module my-module2))</pre>
53
54
55In the near future you will have the following possibilities as well:
56
573) whitelist specific procedures inside a module
58<pre>(whitelist! '((module-name procedure1 procedure2)))</pre>
59
60It is also planned to implement some keywords that allow easier use of this procedure.
61
62
63
64<parameter>dispatch-error</parameter>
65
66If no handler for a uri can be found, the dispatcher will invoke the procedure that dispatch-error is currently parameterized with.
67'''NOTE''' dispatch-error is also invoked if the requested handler exists but is not whitelisted.
68
69<parameter>enable-whitelisting</parameter>
70
71If set to #t then whitelist-checks are enabled. Defaults to #f.
72<parameter>default-dispatch-target</parameter>
73
74A thunk that is invoke when the uri-path was empty. If set to #f then an empty path leads to the invocation of dispatch-error.
75Defaults to #f.
76
77<parameter>dispatch-environment</parameter>
78
79The environment that is used to lookup the procedures. It defaults to '''current-interaction-environment'''.
80
81
82=== Examples
83<pre>
84
85(use spiffy intarweb uri-common uri-dispatch)
86
87(define (my-dispatch-error . path)
88  (send-status 404 (sprintf "My Dispatch-error ~A" path)))
89
90
91(module example
92  (echo webiota)
93  (import scheme chicken srfi-1 extras)
94  (require-library spiffy)
95  (import (only spiffy send-status))
96
97  (define (webiota #!optional (start "0") (steps "10") #!rest rest)
98    (send-status 200 (sprintf "webiota called: ~A" (iota (string->number steps) (string->number start)))))
99
100  (define (echo . args)
101    (send-status 200 (sprintf "echo: ~A" args))))
102
103(define (outsidemodule . args) (send-status 200 "Outside module"))
104
105(vhost-map `(("localhost" . ,(lambda (continue)
106                              (parameterize ((handle-not-found  (lambda (path) (dispatch-uri (request-uri (current-request)))))
107                                             (dispatch-error (lambda path (send-status 404 (sprintf "Path not found: ~A" path)))))
108                                (continue))))))
109(start-server)
110</pre>
111
112Now start the server and visit the following pages:
113* http://localhost:8080/example/webiota/2/10/
114* http://localhost:8080/example/webiota/2/20/
115* http://localhost:8080/example/webiota/echo/this/please
116* http://localhost:8080/outsidemodule
117* http://localhost:8080/i/do/not/exist
Note: See TracBrowser for help on using the repository browser.