-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathroute.scm
70 lines (62 loc) · 2.18 KB
/
route.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
(define-module (schingle route)
#:use-module (web uri)
#:use-module (schingle util)
#:use-module (ice-9 regex)
#:use-module (srfi srfi-9)
#:export (make-router
add-route!
match-route
route-match-route
route-match-captures
route-match-value))
(define-record-type route
(make-route method regex value)
route?
(method route-method)
(regex route-regex)
(value route-value))
(define-record-type router
(make-router-inner routes)
router?
(routes router-routes router-set-routes!))
(define-record-type route-match
(make-route-match route captures value)
route-match?
(route route-match-route)
(captures route-match-captures)
(value route-match-value))
(define (make-router)
(make-router-inner '()))
(define (add-route! router method path value)
(router-set-routes! router (cons (path->route method path value)
(router-routes router))))
(define (match-captures m)
(define (inner n)
(if (= n (match:count m))
'()
(cons (match:substring m n)
(inner (+ n 1)))))
(inner 1))
(define (match-route router method path)
(define (inner routes)
(if (null? routes)
#f
(let ((hit (and (eq? method (route-method (car routes)))
(regexp-exec (route-regex (car routes)) path))))
(if hit
(make-route-match (car routes) (match-captures hit) (route-value (car routes)))
(inner (cdr routes))))))
(inner (router-routes router)))
(define (path->route method path value)
(define parts (split-and-decode-uri-path path))
(make-route method
(make-regexp (string-append "^/*"
(string-join
(map (lambda (part)
(if (equal? #\: (string-ref part 0))
"([^/]+)"
part))
parts)
"/+")
"/*$"))
value))