152 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			152 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Factor
		
	
	
| 
								 | 
							
								! Copyright (C) 2004 Chris Double.
							 | 
						||
| 
								 | 
							
								! See http://factorcode.org/license.txt for BSD license.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								USING: http math namespaces io strings kernel html html.elements
							 | 
						||
| 
								 | 
							
								hashtables continuations quotations parser generic sequences
							 | 
						||
| 
								 | 
							
								webapps.callback http.server.responders ;
							 | 
						||
| 
								 | 
							
								IN: webapps.continuation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#! Used inside the session state of responders to indicate whether the
							 | 
						||
| 
								 | 
							
								#! next request should use the post-refresh-get pattern. It is set to
							 | 
						||
| 
								 | 
							
								#! true after each request.
							 | 
						||
| 
								 | 
							
								SYMBOL: post-refresh-get?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: >callable ( quot|interp|f -- interp )
							 | 
						||
| 
								 | 
							
								    dup continuation? [
							 | 
						||
| 
								 | 
							
								        [ continue ] curry
							 | 
						||
| 
								 | 
							
								    ] when ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: forward-to-url ( url -- )
							 | 
						||
| 
								 | 
							
								    #! When executed inside a 'show' call, this will force a
							 | 
						||
| 
								 | 
							
								    #! HTTP 302 to occur to instruct the browser to forward to
							 | 
						||
| 
								 | 
							
								    #! the request URL.
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        "HTTP/1.1 302 Document Moved\nLocation: " % %
							 | 
						||
| 
								 | 
							
								        "\nContent-Length: 0\nContent-Type: text/plain\n\n" %
							 | 
						||
| 
								 | 
							
								    ] "" make write exit-continuation get continue ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: forward-to-id ( id -- )
							 | 
						||
| 
								 | 
							
								    #! When executed inside a 'show' call, this will force a
							 | 
						||
| 
								 | 
							
								    #! HTTP 302 to occur to instruct the browser to forward to
							 | 
						||
| 
								 | 
							
								    #! the request URL.
							 | 
						||
| 
								 | 
							
								    >r "request" get r> id>url append forward-to-url ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								SYMBOL: current-show
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: store-current-show ( -- )
							 | 
						||
| 
								 | 
							
								  #! Store the current continuation in the variable 'current-show'
							 | 
						||
| 
								 | 
							
								  #! so it can be returned to later by href callbacks. Note that it
							 | 
						||
| 
								 | 
							
								  #! recalls itself when the continuation is called to ensure that
							 | 
						||
| 
								 | 
							
								  #! it resets its value back to the most recent show call.
							 | 
						||
| 
								 | 
							
								  [  ( 0 -- )
							 | 
						||
| 
								 | 
							
								      [ ( 0 1 -- )
							 | 
						||
| 
								 | 
							
								          current-show set ( 0 -- )
							 | 
						||
| 
								 | 
							
								          continue
							 | 
						||
| 
								 | 
							
								      ] callcc1
							 | 
						||
| 
								 | 
							
								      nip
							 | 
						||
| 
								 | 
							
								      restore-request
							 | 
						||
| 
								 | 
							
								      call
							 | 
						||
| 
								 | 
							
								      store-current-show
							 | 
						||
| 
								 | 
							
								  ] callcc0 restore-request ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: redirect-to-here ( -- )
							 | 
						||
| 
								 | 
							
								    #! Force a redirect to the client browser so that the browser
							 | 
						||
| 
								 | 
							
								    #! goes to the current point in the code. This forces an URL
							 | 
						||
| 
								 | 
							
								    #! change on the browser so that refreshing that URL will
							 | 
						||
| 
								 | 
							
								    #! immediately run from this code point. This prevents the
							 | 
						||
| 
								 | 
							
								    #! "this request will issue a POST" warning from the browser
							 | 
						||
| 
								 | 
							
								    #! and prevents re-running the previous POST logic. This is
							 | 
						||
| 
								 | 
							
								    #! known as the 'post-refresh-get' pattern.
							 | 
						||
| 
								 | 
							
								    post-refresh-get? get [
							 | 
						||
| 
								 | 
							
								        [
							 | 
						||
| 
								 | 
							
								            >callable t register-callback forward-to-url
							 | 
						||
| 
								 | 
							
								        ] callcc0  restore-request
							 | 
						||
| 
								 | 
							
								    ] [
							 | 
						||
| 
								 | 
							
								        t post-refresh-get? set
							 | 
						||
| 
								 | 
							
								    ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: (show) ( quot -- hashtable )
							 | 
						||
| 
								 | 
							
								    #! See comments for show. The difference is the
							 | 
						||
| 
								 | 
							
								    #! quotation MUST set the content-type using 'serving-html'
							 | 
						||
| 
								 | 
							
								    #! or similar.
							 | 
						||
| 
								 | 
							
								    store-current-show redirect-to-here
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        >callable t register-callback swap with-scope
							 | 
						||
| 
								 | 
							
								        exit-continuation get  continue
							 | 
						||
| 
								 | 
							
								    ] callcc0 drop restore-request "response" get ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: show ( quot -- namespace )
							 | 
						||
| 
								 | 
							
								    #! Call the quotation with the URL associated with the current
							 | 
						||
| 
								 | 
							
								    #! continuation. All output from the quotation goes to the client
							 | 
						||
| 
								 | 
							
								    #! browser. When the URL is later referenced then
							 | 
						||
| 
								 | 
							
								    #! computation will resume from this 'show' call with a hashtable on
							 | 
						||
| 
								 | 
							
								    #! the stack containing any query or post parameters.
							 | 
						||
| 
								 | 
							
								    #! 'quot' has stack effect ( url -- )
							 | 
						||
| 
								 | 
							
								    #! NOTE: On return from 'show' the stack is exactly the same as
							 | 
						||
| 
								 | 
							
								    #! initial entry with 'quot' popped off and the hashtable pushed on. Even
							 | 
						||
| 
								 | 
							
								    #! if the quotation consumes items on the stack.
							 | 
						||
| 
								 | 
							
								    [ serving-html ] swap append (show) ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: (show-final) ( quot -- namespace )
							 | 
						||
| 
								 | 
							
								    #! See comments for show-final. The difference is the
							 | 
						||
| 
								 | 
							
								    #! quotation MUST set the content-type using 'serving-html'
							 | 
						||
| 
								 | 
							
								    #! or similar.
							 | 
						||
| 
								 | 
							
								    store-current-show redirect-to-here
							 | 
						||
| 
								 | 
							
								    with-scope exit-continuation get continue ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: show-final ( quot -- namespace )
							 | 
						||
| 
								 | 
							
								    #! Similar to 'show', except the quotation does not receive the URL
							 | 
						||
| 
								 | 
							
								    #! to resume computation following 'show-final'. No continuation is
							 | 
						||
| 
								 | 
							
								    #! stored for this resumption. As a result, 'show-final' is for use
							 | 
						||
| 
								 | 
							
								    #! when a page is to be displayed with no further action to occur. Its
							 | 
						||
| 
								 | 
							
								    #! use is an optimisation to save having to generate and save a continuation
							 | 
						||
| 
								 | 
							
								    #! in that special case.
							 | 
						||
| 
								 | 
							
								    #! 'quot' has stack effect ( -- ).
							 | 
						||
| 
								 | 
							
								    [ serving-html ] swap compose (show-final) ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#! Name of variable for holding initial continuation id that starts
							 | 
						||
| 
								 | 
							
								#! the responder.
							 | 
						||
| 
								 | 
							
								SYMBOL: root-callback
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: cont-get/post-responder ( id-or-f -- )
							 | 
						||
| 
								 | 
							
								    #! httpd responder that handles the root continuation request.
							 | 
						||
| 
								 | 
							
								    #! The requests for actual continuation are processed by the
							 | 
						||
| 
								 | 
							
								    #! 'callback-responder'.
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        [ f post-refresh-get? set <request> request set root-callback get call ] with-scope
							 | 
						||
| 
								 | 
							
								        exit-continuation get continue
							 | 
						||
| 
								 | 
							
								    ] with-exit-continuation  drop ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: quot-url ( quot -- url )
							 | 
						||
| 
								 | 
							
								    current-show get [ continue-with ] 2curry t register-callback ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: quot-href ( text quot -- )
							 | 
						||
| 
								 | 
							
								    #! Write to standard output an HTML HREF where the href,
							 | 
						||
| 
								 | 
							
								    #! when referenced, will call the quotation and then return
							 | 
						||
| 
								 | 
							
								    #! back to the most recent 'show' call (via the callback-cc).
							 | 
						||
| 
								 | 
							
								    #! The text of the link will be the 'text' argument on the
							 | 
						||
| 
								 | 
							
								    #! stack.
							 | 
						||
| 
								 | 
							
								    <a quot-url =href a> write </a> ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: install-cont-responder ( name quot -- )
							 | 
						||
| 
								 | 
							
								    #! Install a cont-responder with the given name
							 | 
						||
| 
								 | 
							
								    #! that will initially run the given quotation.
							 | 
						||
| 
								 | 
							
								    #!
							 | 
						||
| 
								 | 
							
								    #! Convert the quotation so it is run within a session namespace
							 | 
						||
| 
								 | 
							
								    #! and that namespace is initialized first.
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        [ cont-get/post-responder ] "get" set
							 | 
						||
| 
								 | 
							
								        [ cont-get/post-responder ] "post" set
							 | 
						||
| 
								 | 
							
								        swap "responder" set
							 | 
						||
| 
								 | 
							
								        root-callback set
							 | 
						||
| 
								 | 
							
								    ] make-responder ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: show-message-page ( message -- )
							 | 
						||
| 
								 | 
							
								    #! Display the message in an HTML page with an OK button.
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        "Press OK to Continue" [
							 | 
						||
| 
								 | 
							
								            swap paragraph
							 | 
						||
| 
								 | 
							
								            <a =href a> "OK" write </a>
							 | 
						||
| 
								 | 
							
								        ] simple-page
							 | 
						||
| 
								 | 
							
								    ] show 2drop ;
							 |