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

Last change on this file since 15648 was 15648, checked in by certainty, 10 years ago

Changes applied for certainty (82.83.157.152) through svnwiki:

  • Property svnwiki:tags set to web
  • Property svnwiki:title set to uri-dispatch
File size: 5.0 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''' See also the whitelisting-section, to learn how to limit the exposure of procdures)
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 lambda-lists to declare optional arguments or a rest-argument.
39
40All those lookups are done in the current '''dispatch-environment''', which can be parameterized.
41
42
43==== Whitelisting
44
45Though nice for development it is not advisable to allow everybody out there to invoke abritary procedures of your application.
46So you might want to whitelist only those procedures that really acts as the interface of your application.
47
48To enable whitelisting you simply parameterize the '''whitelist''' parameter with your whitelisting-specification.
49If a procedure is requested that does exist but is not whitelisted '''dispatch-error''' is invoked.
50
51
52'''Whitelisting specification'''
53
54The whitelist allows to selectivly whitelist procedures modules and procedures inside modules.
55The examples explain all three cases
56
57 (whitelist '(proc1 proc2 proc3))
58
59This will whitelist the procedures proc1..proc3. Those procedures must be defined outside a module.
60
61 (whitelist '((mod1 . (proc1 proc2))
62
63This will whitelist the procedures proc1 and proc2 that must reside inside the module mod1.
64
65 (whitelist '((mod1 . *))
66
67This will whitelist all procedures inside the module mod1.
68
69Of course you can mix those declarations.
70
71
72<parameter>whitelist</parameter>
73
74The parameter holding the whitelist. It defaults to #f which means whitelisting is disabled.
75
76
77<parameter>dispatch-error</parameter>
78
79If no handler for a uri can be found, the dispatcher will invoke the procedure that dispatch-error is currently parameterized with.
80'''NOTE''' dispatch-error is also invoked if the requested handler exists but is not whitelisted.
81Defaults to (constantly #f).
82
83<parameter>enable-whitelisting</parameter>
84
85If set to #t then whitelist-checks are enabled. Defaults to #f.
86
87<parameter>default-dispatch-target</parameter>
88
89A 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.
90Defaults to #f.
91
92<parameter>dispatch-environment</parameter>
93The environment that is used to lookup the procedures. It defaults to '''interaction-environment'''.
94
95
96=== Examples
97<pre>
98
99(use spiffy intarweb uri-common uri-dispatch)
100
101(define (my-dispatch-error . path)
102  (send-status 404 (sprintf "My Dispatch-error ~A" path)))
103
104
105(module example
106  (echo webiota)
107  (import scheme chicken srfi-1 extras)
108  (require-library spiffy)
109  (import (only spiffy send-status))
110
111  (define (webiota #!optional (start "0") (steps "10") #!rest rest)
112    (send-status 200 (sprintf "webiota called: ~A" (iota (string->number steps) (string->number start)))))
113
114  (define (echo . args)
115    (send-status 200 (sprintf "echo: ~A" args))))
116
117(define (outsidemodule . args) (send-status 200 "Outside module"))
118
119(vhost-map `(("localhost" . ,(lambda (continue)
120                              (parameterize ((handle-not-found  (lambda (path) (dispatch-uri (request-uri (current-request)))))
121                                             (dispatch-error (lambda path (send-status 404 (sprintf "Path not found: ~A" path)))))
122                                (continue))))))
123(start-server)
124</pre>
125
126Now start the server and visit the following pages:
127* http://localhost:8080/example/webiota/2/10/
128* http://localhost:8080/example/webiota/2/20/
129* http://localhost:8080/example/echo/this/please
130* http://localhost:8080/outsidemodule
131* http://localhost:8080/i/do/not/exist
Note: See TracBrowser for help on using the repository browser.