]> gitweb.factorcode.org Git - factor.git/blob - basis/furnace/utilities/utilities.factor
57a6919ae92459fa6ece6c9b143b14fea224f5a3
[factor.git] / basis / furnace / utilities / utilities.factor
1 ! Copyright (C) 2008, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs classes combinators continuations
4 definitions fry http http.server http.server.redirection
5 http.server.remapping io.pathnames kernel make namespaces
6 sequences splitting strings urls words xml.syntax ;
7 IN: furnace.utilities
8
9 : word>string ( word -- string )
10     [ vocabulary>> ] [ name>> ] bi ":" glue ;
11
12 : words>strings ( seq -- seq' )
13     [ word>string ] map ;
14
15 ERROR: no-such-word name vocab ;
16
17 : string>word ( string -- word )
18     ":" split1 swap 2dup lookup-word dup
19     [ 2nip ] [ drop no-such-word ] if ;
20
21 : strings>words ( seq -- seq' )
22     [ string>word ] map ;
23
24 : nested-responders ( -- seq )
25     responder-nesting get values ;
26
27 : each-responder ( quot: ( ... responder -- ... ) -- )
28    nested-responders swap each ; inline
29
30 ERROR: no-such-responder responder ;
31
32 : base-path ( string -- seq )
33     dup responder-nesting get
34     [ second class-of superclasses-of [ name>> = ] with any? ] with find nip
35     [ first ] [ no-such-responder ] ?if ;
36
37 : resolve-base-path ( string -- string' )
38     "$" ?head [
39         [
40             "/" split1 [ base-path [ "/" % % ] each "/" % ] dip %
41         ] "" make
42     ] when ;
43
44 : resolve-word-path ( word -- path/f )
45     where [ first parent-directory ] [ f ] if* ;
46
47 : resolve-template-path ( pair -- path )
48     first2 [ resolve-word-path ] dip append-path ;
49
50 GENERIC: modify-query ( query responder -- query' )
51
52 M: object modify-query drop ;
53
54 GENERIC: modify-redirect-query ( query responder -- query' )
55
56 M: object modify-redirect-query drop ;
57
58 GENERIC: adjust-url ( url -- url' )
59
60 M: url adjust-url
61     clone
62         [ [ modify-query ] each-responder ] change-query
63         [ resolve-base-path ] change-path
64     relative-to-request ;
65
66 M: string adjust-url ;
67
68 GENERIC: adjust-redirect-url ( url -- url' )
69
70 M: url adjust-redirect-url
71     adjust-url
72     [ [ modify-redirect-query ] each-responder ] change-query ;
73
74 M: string adjust-redirect-url ;
75
76 GENERIC: link-attr ( tag responder -- )
77
78 M: object link-attr 2drop ;
79
80 GENERIC: modify-form ( responder -- xml/f )
81
82 M: object modify-form drop f ;
83
84 : form-modifications ( -- xml )
85     [ [ modify-form [ , ] when* ] each-responder ] { } make ;
86
87 : hidden-form-field ( value name -- xml )
88     over [
89         [XML <input type="hidden" value=<-> name=<->/> XML]
90     ] [ drop ] if ;
91
92 CONSTANT: nested-forms-key "__n"
93
94 : referrer ( -- referrer/f )
95     #! Typo is intentional, it's in the HTTP spec!
96     request get "referer" header
97     dup [ >url ensure-port [ remap-port ] change-port ] when ;
98
99 : user-agent ( -- user-agent )
100     request get "user-agent" header "" or ;
101
102 : same-host? ( url -- ? )
103     dup [
104         url get [
105             [ protocol>> ]
106             [ host>> ]
107             [ port>> remap-port ]
108             tri 3array
109         ] same?
110     ] when ;
111
112 : cookie-client-state ( key request -- value/f )
113     swap get-cookie dup [ value>> ] when ;
114
115 : post-client-state ( key request -- value/f )
116     request-params at ;
117
118 : client-state ( key -- value/f )
119     request get dup method>> {
120         { "GET" [ cookie-client-state ] }
121         { "HEAD" [ cookie-client-state ] }
122         { "POST" [ post-client-state ] }
123     } case ;
124
125 SYMBOL: exit-continuation
126
127 : exit-with ( value -- * )
128     exit-continuation get continue-with ;
129
130 : with-exit-continuation ( quot -- value )
131     '[ exit-continuation set @ ] callcc1 exit-continuation off ; inline