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

Last change on this file since 15379 was 15379, checked in by certainty, 10 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-checks''' 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-checks''' 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 three 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
543) whitelist specific procedures inside a module
55<pre>(whitelist! '((module-name procedure1 procedure2)))</pre>
56
57As noted above you can mix those possibilities
58
59<pre>(whitelist! '(proc1 proc2 proc3 (module foo-mod bar-mod) (baz-module proc4 proc5)))</pre>
60
61It is planned to implement some keywords that allow easier use of this procedure.
62
63
64
65<parameter>dispatch-error</parameter>
66
67If no handler for a uri can be found, the dispatcher will invoke the procedure that dispatch-error is currently parameterized with.
68'''NOTE''' dispatch-error is also invoked if the requested handler exists but is not whitelisted.
69
70<parameter>enable-checks</parameter>
71
72If set to #t then whitelist-checks are enabled. Defaults to #f.
73
74<parameter>default-dispatch-target</parameter>
75
76A 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.
77Defaults to #f.
78
79<parameter>dispatch-environment</parameter>
80
81The environment that is used to lookup the procedures. It defaults to '''current-interaction-environment'''.
82
83
84=== Examples
85<pre>
86
87(use spiffy intarweb uri-common uri-dispatch)
88
89(define (my-dispatch-error . path)
90  (send-status 404 (sprintf "My Dispatch-error ~A" path)))
91
92
93(module example
94  (echo webiota)
95  (import scheme chicken srfi-1 extras)
96  (require-library spiffy)
97  (import (only spiffy send-status))
98
99  (define (webiota #!optional (start "0") (steps "10") #!rest rest)
100    (send-status 200 (sprintf "webiota called: ~A" (iota (string->number steps) (string->number start)))))
101
102  (define (echo . args)
103    (send-status 200 (sprintf "echo: ~A" args))))
104
105(define (outsidemodule . args) (send-status 200 "Outside module"))
106
107(vhost-map `(("localhost" . ,(lambda (continue)
108                              (parameterize ((handle-not-found  (lambda (path) (dispatch-uri (request-uri (current-request)))))
109                                             (dispatch-error (lambda path (send-status 404 (sprintf "Path not found: ~A" path)))))
110                                (continue))))))
111(start-server)
112</pre>
113
114Now start the server and visit the following pages:
115* http://localhost:8080/example/webiota/2/10/
116* http://localhost:8080/example/webiota/2/20/
117* http://localhost:8080/example/webiota/echo/this/please
118* http://localhost:8080/outsidemodule
119* http://localhost:8080/i/do/not/exist
Note: See TracBrowser for help on using the repository browser.