1 ! Copyright (C) 2004 Chris Double.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: http httpd math namespaces io strings kernel html hashtables
5 parser generic sequences callback-responder ;
8 #! Used inside the session state of responders to indicate whether the
9 #! next request should use the post-refresh-get pattern. It is set to
10 #! true after each request.
11 SYMBOL: post-refresh-get?
13 : >callable ( quot|interp|f -- interp )
18 : forward-to-url ( url -- )
19 #! When executed inside a 'show' call, this will force a
20 #! HTTP 302 to occur to instruct the browser to forward to
23 "HTTP/1.1 302 Document Moved\nLocation: " % %
24 "\nContent-Length: 0\nContent-Type: text/plain\n\n" %
25 ] "" make write exit-continuation get continue ;
27 : forward-to-id ( id -- )
28 #! When executed inside a 'show' call, this will force a
29 #! HTTP 302 to occur to instruct the browser to forward to
31 >r "request" get r> id>url append forward-to-url ;
35 : store-current-show ( -- )
36 #! Store the current continuation in the variable 'current-show'
37 #! so it can be returned to later by href callbacks. Note that it
38 #! recalls itself when the continuation is called to ensure that
39 #! it resets its value back to the most recent show call.
42 current-show set ( 0 -- )
49 ] callcc0 restore-request ;
51 : redirect-to-here ( -- )
52 #! Force a redirect to the client browser so that the browser
53 #! goes to the current point in the code. This forces an URL
54 #! change on the browser so that refreshing that URL will
55 #! immediately run from this code point. This prevents the
56 #! "this request will issue a POST" warning from the browser
57 #! and prevents re-running the previous POST logic. This is
58 #! known as the 'post-refresh-get' pattern.
59 post-refresh-get? get [
61 >callable t register-callback forward-to-url
62 ] callcc1 drop restore-request
64 t post-refresh-get? set
67 : (show) ( quot -- hashtable )
68 #! See comments for show. The difference is the
69 #! quotation MUST set the content-type using 'serving-html'
71 store-current-show redirect-to-here
73 >callable t register-callback swap with-scope
74 exit-continuation get continue
75 ] callcc0 drop restore-request "response" get ;
77 : show ( quot -- namespace )
78 #! Call the quotation with the URL associated with the current
79 #! continuation. All output from the quotation goes to the client
80 #! browser. When the URL is later referenced then
81 #! computation will resume from this 'show' call with a hashtable on
82 #! the stack containing any query or post parameters.
83 #! 'quot' has stack effect ( url -- )
84 #! NOTE: On return from 'show' the stack is exactly the same as
85 #! initial entry with 'quot' popped off and the hashtable pushed on. Even
86 #! if the quotation consumes items on the stack.
87 [ serving-html ] swap append (show) ;
89 : (show-final) ( quot -- namespace )
90 #! See comments for show-final. The difference is the
91 #! quotation MUST set the content-type using 'serving-html'
93 store-current-show redirect-to-here
94 with-scope exit-continuation get continue ;
96 : show-final ( quot -- namespace )
97 #! Similar to 'show', except the quotation does not receive the URL
98 #! to resume computation following 'show-final'. No continuation is
99 #! stored for this resumption. As a result, 'show-final' is for use
100 #! when a page is to be displayed with no further action to occur. Its
101 #! use is an optimisation to save having to generate and save a continuation
102 #! in that special case.
103 #! 'quot' has stack effect ( -- ).
104 [ serving-html ] swap append (show-final) ;
106 #! Name of variable for holding initial continuation id that starts
108 SYMBOL: root-callback
110 : cont-get/post-responder ( id-or-f -- )
111 #! httpd responder that handles the root continuation request.
112 #! The requests for actual continuation are processed by the
113 #! 'callback-responder'.
115 [ f post-refresh-get? set <request> request set root-callback get call ] with-scope
116 exit-continuation get continue
117 ] with-exit-continuation drop ;
119 : quot-url ( quot -- url )
120 current-show get [ continue-with ] curry curry t register-callback ;
122 : quot-href ( text quot -- )
123 #! Write to standard output an HTML HREF where the href,
124 #! when referenced, will call the quotation and then return
125 #! back to the most recent 'show' call (via the callback-cc).
126 #! The text of the link will be the 'text' argument on the
128 <a quot-url =href a> write </a> ;
130 : install-cont-responder ( name quot -- )
131 #! Install a cont-responder with the given name
132 #! that will initially run the given quotation.
134 #! Convert the quotation so it is run within a session namespace
135 #! and that namespace is initialized first.
137 [ cont-get/post-responder ] "get" set
138 [ cont-get/post-responder ] "post" set
143 : simple-page ( title quot -- )
144 #! Call the quotation, with all output going to the
145 #! body of an html page with the given title.
147 <head> <title> swap write </title> </head>
151 : styled-page ( title stylesheet-quot quot -- )
152 #! Call the quotation, with all output going to the
153 #! body of an html page with the given title. stylesheet-quot
154 #! is called to generate the required stylesheet.
157 <title> rot write </title>
163 : paragraph ( str -- )
164 #! Output the string as an html paragraph
167 : show-message-page ( message -- )
168 #! Display the message in an HTML page with an OK button.
170 "Press OK to Continue" [
172 <a =href a> "OK" write </a>
176 : vertical-layout ( list -- )
177 #! Given a list of HTML components, arrange them vertically.
179 [ <tr> <td> call </td> </tr> ] each
182 : horizontal-layout ( list -- )
183 #! Given a list of HTML components, arrange them horizontally.
185 <tr "top" =valign tr> [ <td> call </td> ] each </tr>
188 : button ( label -- )
189 #! Output an HTML submit button with the given label.
190 <input "submit" =type =value input/> ;