1 ! Copyright (C) 2004 Chris Double.
\r
2 ! Copyright (C) 2006, 2008 Slava Pestov.
\r
3 ! See http://factorcode.org/license.txt for BSD license.
\r
4 USING: http http.server io kernel math namespaces
\r
5 continuations calendar sequences assocs hashtables
\r
6 accessors arrays alarms quotations combinators fry
\r
7 http.server.redirection furnace assocs.lib urls ;
\r
8 IN: furnace.callbacks
\r
12 TUPLE: callback-responder responder callbacks ;
\r
14 : <callback-responder> ( responder -- responder' )
\r
15 H{ } clone callback-responder boa ;
\r
17 TUPLE: callback cont quot expires alarm responder ;
\r
19 : timeout 20 minutes ;
\r
21 : timeout-callback ( callback -- )
\r
22 [ alarm>> cancel-alarm ]
\r
23 [ dup responder>> callbacks>> delete-at ]
\r
26 : touch-callback ( callback -- )
\r
28 dup alarm>> [ cancel-alarm ] when*
\r
29 dup '[ , timeout-callback ] timeout later >>alarm
\r
32 : <callback> ( cont quot expires? -- callback )
\r
33 f callback-responder get callback boa
\r
34 dup touch-callback ;
\r
36 : invoke-callback ( callback -- response )
\r
38 [ quot>> request get exit-continuation get 3array ]
\r
39 [ cont>> continue-with ]
\r
42 : register-callback ( cont quot expires? -- id )
\r
43 <callback> callback-responder get callbacks>> set-at-unique ;
\r
45 : forward-to-url ( url -- * )
\r
46 #! When executed inside a 'show' call, this will force a
\r
47 #! HTTP 302 to occur to instruct the browser to forward to
\r
49 <temporary-redirect> exit-with ;
\r
51 : cont-id "factorcontid" ;
\r
53 : forward-to-id ( id -- * )
\r
54 #! When executed inside a 'show' call, this will force a
\r
55 #! HTTP 302 to occur to instruct the browser to forward to
\r
58 swap cont-id set-query-param forward-to-url ;
\r
60 : restore-request ( pair -- )
\r
61 first3 exit-continuation set request set call ;
\r
63 SYMBOL: post-refresh-get?
\r
65 : redirect-to-here ( -- )
\r
66 #! Force a redirect to the client browser so that the browser
\r
67 #! goes to the current point in the code. This forces an URL
\r
68 #! change on the browser so that refreshing that URL will
\r
69 #! immediately run from this code point. This prevents the
\r
70 #! "this request will issue a POST" warning from the browser
\r
71 #! and prevents re-running the previous POST logic. This is
\r
72 #! known as the 'post-refresh-get' pattern.
\r
73 post-refresh-get? get [
\r
75 [ ] t register-callback forward-to-id
\r
76 ] callcc1 restore-request
\r
78 post-refresh-get? on
\r
81 SYMBOL: current-show
\r
83 : store-current-show ( -- )
\r
84 #! Store the current continuation in the variable 'current-show'
\r
85 #! so it can be returned to later by 'quot-id'. Note that it
\r
86 #! recalls itself when the continuation is called to ensure that
\r
87 #! it resets its value back to the most recent show call.
\r
88 [ current-show set f ] callcc1
\r
89 [ restore-request store-current-show ] when* ;
\r
91 : show-final ( quot -- * )
\r
92 [ redirect-to-here store-current-show ] dip
\r
93 call exit-with ; inline
\r
95 : resuming-callback ( responder request -- id )
\r
96 url>> cont-id query-param swap callbacks>> at ;
\r
98 M: callback-responder call-responder* ( path responder -- response )
\r
102 [ callback-responder set ]
\r
103 [ request get resuming-callback ] bi
\r
108 callback-responder get responder>> call-responder
\r
110 ] with-exit-continuation ;
\r
112 : show-page ( quot -- )
\r
113 [ redirect-to-here store-current-show ] dip
\r
115 [ ] t register-callback swap call exit-with
\r
116 ] callcc1 restore-request ; inline
\r
118 : quot-id ( quot -- id )
\r
119 current-show get swap t register-callback ;
\r
121 : quot-url ( quot -- url )
\r
122 quot-id f swap cont-id associate derive-url ;
\r