Domains/Coco

(Parent)

Tcl8.6 Coroutine domain. Invoking the domain URL creates a coroutine with semantics given by a lambda (evaluated within the Coco namespace,) and associates this running coroutine with an automatically-generated URL. The domain URL invocation, having generated its coroutine, redirects to it. Coco is like a [Direct] domain except the functional element is a coroutine not a namespace or object instance. The coroutine created by invoking a Coco domain has a unique name which will persist until the coroutine exits or until the server restarts. Coroutines maintain their local variable state, so Coco may be used to maintain persistent state for as long as the coroutine exists. It is possible, therefore, to use Coco as the basis of a session facility. The Cocoroutine is called with the request dict. [[yield]] may return a response to that request, which will subsequently be returned to the client. If [[yield]] is called without an argument, it returns an HTTP redirect to the coroutine's URL. == Coco Forms == Since Coco provides lightweight session persistence, keyed by synthetic URL, it can be used to validate forms. The [[Coco form]] command is invoked as ''[[Coco form $request $form [[list $fail_message $predicate]] ... ]]''. Where $request is the current HTTP request dict, $form is an HTML form (with an optional %MESSAGE string embedded), and args are a validation dict. Validation dicts associate the name of a field in the form with a list comprising a message to be displayed if the validation fails, and a tcl validation expression or predicate. The predicate may be anything acceptable to Tcl's [[expr]], and is expected to return a boolean value. All form fields are available to each predicate as tcl variables of the same name. [[Coco form]] will cause the Coco coroutine to re-issue the form until all validation predicates evaluate true. === Example: validating a form === [[Coco form]] provides a form validation facility. Once called, it will return the supplied form until all validation predicates are true. Nub domain /copf/ Coco lambda {r { set referer [Http Referer $r] ;# remember referer set r [yield] ;# initially just redirect set prefix "[

"Personal Information"][

"Referer: '$referer'"]" set suffix [

[clock format [clock seconds]]] # validate the supplied form against a dict of field/validators set r [my Form $r info -prefix $prefix -suffix $suffix {

class message [join %MESSAGE%
] fieldset personal { legend [ submit "Personal Information"] text forename title "Forename" -invalid "Forename can't be empty" -validate {$forename ne ""} text surname title "Surname" -invalid "Surname can't be empty." -validate {$surname ne ""} [
] text phone title "Phone number" -invalid "Phone number has to look like a phone number." -validate {[regexp {^[-0-9+ ]+$} $phone]} } }] # now all the variable/fields mentioned in [form] have valid values # resume where you were return [Http Redirect $r $referer] }} == Examples == === Simple interaction example === This Cocoroutine returns a simple form, collects its response, echoes it to the client, and terminates. Nub domain /said/ Coco lambda {r { set r [yield [Http Ok+ [yield] [

said "[ stuff][ ok]"]]] Query qvars [Query parse $r] stuff ;# fetch $stuff from the submitted form return [Http Ok+ [yield [Http Ok+ $r [ href . "click here"]]] [

"You said: $stuff"]] # this coroutine is a one-shot - as it returns, the coroutine will disappear }} === Example: Counting calls === The following just counts calls to the synthetic URL Nub domain /coco/ Coco lambda {r { set r [yield] ;# initially just redirect to this coroutine while {1} { # this coroutine loops around counting calls in $n set content [

"Coco - Coroutining"] append content [

"You have called the coroutine [incr n] times."] set r [yield [Http Ok [Http NoCache $r] $content]] } }} === Referenced in Examples === ;[http:Nub domain]: a command which construct a nub, mapping a URL-glob onto a domain handler (in this case, Coco.) ;[http:../Utility/Http Http]: a module to transform request dicts into response dicts suitable for returning to the client. In summary, [[Http Ok]] generates a normal HTTP Ok response, [[Http Redirect]] generates an HTTP Redirect response, and so on. ;[http:../Utility/Query Query]: a module to parse and manipulate the GET-query or POST-entity components of a request. ;<*>: commands of this form are defined by the [http:../Utility/Html Html] generator package and the [http:../Utility/Form Form] generator package.