Index: embedded/www/index.html ================================================================== --- embedded/www/index.html +++ embedded/www/index.html @@ -2343,11 +2343,11 @@ grammar::me_intro · grammar::peg::interp · pt · pt::ast · pt::cparam::configuration::critcl · pt::cparam::configuration::tea · pt::json_language · pt::param · pt::pe · pt::pe::op · pt::peg · pt::peg::container · pt::peg::container::peg · pt::peg::export · pt::peg::export::container · pt::peg::export::json · pt::peg::export::peg · pt::peg::from::container · pt::peg::from::json · pt::peg::from::peg · pt::peg::import · pt::peg::import::container · pt::peg::import::json · pt::peg::import::peg · pt::peg::interp · pt::peg::to::container · pt::peg::to::cparam · pt::peg::to::json · pt::peg::to::param · pt::peg::to::peg · pt::peg::to::tclparam · pt::peg_language · pt::pegrammar · pt::pgen · pt::rde · pt::tclparam::configuration::nx · pt::tclparam::configuration::snit · pt::tclparam::configuration::tcloo · pt::util · pt_export_api · pt_import_api · pt_introduction · pt_parse_peg · pt_parser_api · pt_peg_op · struct::graph::op
clay - A minimalist framework for large scale OO Projects
+Clay introduces a method ensemble to both oo::class and oo::object called +clay. This ensemble handles all of the high level interactions within the framework. +Clay stores structured data. Clan manages method delegation. Clay has facilities to +manage the complex interactions that come about with mixins.
+The central concept is that inside of every object and class +(which are actually objects too) is a dict called clay. What is stored in that dict is +left to the imagination. But because this dict is exposed via a public method, we can +share structured data between object, classes, and mixins.
+Clay uses a standardized set of method interactions and introspection that TclOO already provides to perform on-the-fly searches. On-the-fly searches mean that the data is never stale, and we avoid many of the sorts of collisions that would arise when objects start mixing in other classes during operation.
+The clay methods for both classes and objects have a get and a set method. For objects, get will search through the local clay dict. If the requested leaf is not found, or the query is for a branch, the system will then begin to poll the clay methods of all of the class that implements the object, all of that classes’ ancestors, as well as all of the classes that have been mixed into this object, and all of their ancestors.
+Intended branches on a tree end with a directory slash (/). Intended leaves are left unadorned. This is a guide for the tool that builds the search +results to know what parts of a dict are intended to be branches and which are intended to be leaves. +For simple cases, branch marking can be ignored:
++::oo::class create ::foo { } +::foo clay set property/ color blue +::foo clay set property/ shape round +set A [::foo new] +$A clay get property/ +{color blue shape round} +$A clay set property/ shape square +$A clay get property/ +{color blue shape square} ++
But when you start storing blocks of text, guessing what field is a dict and what isn’t gets messy:
++::foo clay set description {A generic thing of designated color and shape} +$A clay get description +{A generic thing of designated color and shape} +Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong: +::oo::class create ::foo { } +# Add description as a leaf +::foo clay set description {A generic thing of designated color and shape} +# Add description as a branch +::foo clay set description/ {A generic thing of designated color and shape} +::oo::class create ::bar { + superclass foo +} +# Add description as a leaf +::bar clay set description {A drinking establishment of designated color and shape and size} +# Add description as a branch +::bar clay set description/ {A drinking establishment of designated color and shape and size} +set B [::bar new] +# As a leaf we get the value verbatim from he nearest ancestor +$B clay get description + {A drinking establishment of designated color and shape and size} +# As a branch we get a recursive merge +$B clay get description/ +{A drinking establishment of designated color and size thing of} ++
Clay is built using the oo::dialect module from Tcllib. oo::dialect allows you to either add keywords directly to clay, or to create your own +metaclass and keyword set using Clay as a foundation. For details on the keywords and what they do, consult the functions in the ::clay::define namespace.
+Method Delegation +It is sometimes useful to have an external object that can be invoked as if it were a method of the object. Clay provides a delegate ensemble method to perform that delegation, as well as introspect which methods are delegated in that manner. All delegated methods are marked with html-like tag markings (< >) around them.
++::clay::define counter { + Variable counter 0 + method incr {{howmuch 1}} { + my variable counter + incr counter $howmuch + } + method value {} { + my variable counter + return $counter + } + method reset {} { + my variable counter + set counter 0 + } +} +::clay::define example { + variable buffer + constructor {} { + # Build a counter object + set obj [namespace current]::counter + ::counter create $obj + # Delegate the counter + my delegate <counter> $obj + } + method line {text} { + my <counter> incr + append buffer $text + } +} +set A [example new] +$A line {Who’s line is it anyway?} +$A <counter> value +1 ++
Append a line of text to a variable. Optionally apply a string mapping.
New OO Keywords for clay
This keyword can also be expressed:
+property variable NAME {default DEFAULT}+
Variables registered in the variable property are also initialized + (if missing) when the object changes class via the morph method.
Concatenate a file
Strip the global comments from tcl code. Used to + prevent the documentation markup comments from clogging + up files intended for distribution in machine readable format.
Methods
+Return this class and all ancestors in search order.
Return a complete dump of this object's clay data, but only this object's clay data.
Pull a chunk of data from the clay system. If the last element of path is a branch (ends in a slash /), + returns a recursive merge of all data from this object and it's constituent classes of the data in that branch. + If the last element is a leaf, search this object for a matching leaf, or search all constituent classes for a matching + leaf and return the first value found. + If no value is found, returns an empty string.
Recursively merge the dictionaries given into the object's local clay storage.
Replace the contents of the internal clay storage with the dictionary given.
Return the first matching value for the path in either this class's clay data or one of its ancestors
Merge the conents of value with the object's clay storage at path.
Methods
+Return the class this object belongs to, all classes mixed into this object, and all ancestors of those classes in search order.
Pull a value from either the object's clay structure or one of its constituent classes that matches the field name. + The order of search us:
+1. The as a value in local dict variable config
+2. The as a value in local dict variable clay
+3. As a leaf in any ancestor as a root of the clay tree
+4. As a leaf in any ancestor under the const/ branch of the clay tree
Introspect or control method delegation. With no arguments, the method will return a + key/value list of stubs and objects. With just the stub argument, the method will + return the object (if any) attached to the stub. With a stub and an object + this command will forward all calls to the method stub to the object.
Return a complete dump of this object's clay data, as well as the data from all constituent classes recursively blended in.
Return a dictionary describing the method ensembles to be assembled for this object
Evaluated a script in the namespace of this object
Trigger the InitializePublic private method
Returns 1 if path exists in either the object's clay data. Values greater than one indicate the element exists in one of the object's constituent classes. A value of zero indicates the path could not be found.
Wipe any caches built by the clay implementation
A convenience wrapper for
+oo::objdefine [self] forward {*}$args+
Pull a chunk of data from the clay system. If the last element of path is a branch (ends in a slash /), + returns a recursive merge of all data from this object and it's constituent classes of the data in that branch. + If the last element is a leaf, search this object for a matching leaf, or search all constituent classes for a matching + leaf and return the first value found. + If no value is found, returns an empty string.
A modified get which is tailored to pull only leaf elements
Recursively merge the dictionaries given into the object's local clay storage.
Perform [oo::objdefine [self] mixin] on this object, with a few additional rules: + Prior to the call, for any class was previously mixed in, but not in the new result, execute the script registered to mixin/ unmap-script (if given.) + For all new classes, that were not present prior to this call, after the native TclOO mixin is invoked, execute the script registered to mixin/ map-script (if given.) + Fall all classes that are now present and “mixed in”, execute the script registered to mixin/ react-script (if given.)
With no arguments returns the map of stubs and classes mixed into the current object. When only stub is given, + returns the classes mixed in on that stub. When stub and classlist given, replace the classes currently on that stub with the given + classes and invoke clay mixin on the new matrix of mixed in classes.
Return either self if that path exists in the current object, or return the first class (if any) along the clay search path which contains that element.
Replace the contents of the internal clay storage with the dictionary given.
Source the given filename within the object's namespace
Merge the conents of value with the object's clay storage at path.
Instantiate variables. Called on object creation and during clay mixin.
clay::object + This class is inherited by all classes that have options.
+Methods
+Instantiate variables and build ensemble methods.
{ set authors { + {John Doe} {jdoe@illustrious.edu} + {Tom RichardHarry} {tomdickharry@illustrius.edu} + } + # Create the object + ::clay::doctool create AutoDoc + set fout [open [file join $moddir module.tcl] w] + foreach file [glob [file join $srcdir *.tcl]] { + set content [::clay::cat [file join $srcdir $file]] + # Scan the file + AutoDoc scan_text $content + # Strip the comments from the distribution + puts $fout [::clay::docstrip $content] + } + # Write out the manual page + set manout [open [file join $moddir module.man] w] + dict set arglist header [string map $modmap [::clay::cat [file join $srcdir manual.txt]]] + dict set arglist footer [string map $modmap [::clay::cat [file join $srcdir footer.txt]]] + dict set arglist authors $authors + puts $manout [AutoDoc manpage {*}$arglist] + close $manout +}+
Tool for build scripts to dynamically generate manual files from comments + in source code files
+Methods
+Process an argument list into an informational dict. + This method also understands non-positional + arguments expressed in the notation of Tip 471 + https://core.tcl-lang.org/tips/doc/trunk/tip/479.md.
+The output will be a dictionary of all of the fields and whether the fields + are positional, mandatory, and whether they have a + default value.
+Example:
+my arglist {a b {c 10}} + > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10} ++
Convert a block of comments into an informational dictionary. + If lines in the comment start with a single word ending in a colon, + all subsequent lines are appended to a dictionary field of that name. + If no fields are given, all of the text is appended to the description + field.
+Example:
+my comment {Does something cool} + > description {Does something cool} + my comment { + title : Something really cool + author : Sean Woods + author : John Doe + description : + This does something really cool! + } + > description {This does something really cool!} + title {Something really cool} + author {Sean Woods + John Doe} ++
Process an oo::objdefine call that modifies the class object + itself
Process an oo::define, clay::define, etc statement.
Process a statement for a clay style class method
Process a statement for a tcloo style object method
Process a proc statement
Reset the state of the object and its embedded coroutine
Main body of the embedded coroutine for the object
Generate the manual page text for a method or proc
Generate the manual page text for a class
Generate the manual page text for the commands section
Generate the manual page. Returns the completed text suitable for saving in .man file. + The header argument is a block of doctools text to go in before the machine generated + section. footer is a block of doctools text to go in after the machine generated + section. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?...
Scan a block of text
Scan a file of text
Sean Woods mailto:<yoda@etoyoc.com>
+This document, and the package it describes, will undoubtedly contain +bugs and other problems. +Please report such in the category oo of the +Tcllib Trackers. +Please also report any ideas for enhancements you may have for either +package and/or documentation.
+When proposing code changes, please provide unified diffs, +i.e the output of diff -u.
+Note further that attachments are strongly preferred over +inlined patches. Attachments can be made by going to the Edit +form of the ticket immediately after its creation, and then using the +left-most button in the secondary navigation bar.
+TclOO, oo
+Programming tools
+Copyright © 2018 Sean Woods <yoda@etoyoc.com>
+Returns a dict describing process. See ::cron::task set for a description of the options.
If process does not exist, it is created. Options Include:
If coroutine is black, a global command which implements this process. If coroutine is not +black, the command to invoke to create or recreate the coroutine.
The name of the coroutine (if any) which implements this process.
If -1, this process is terminated after the next event. If 0 this process should be called during every +idle event. If positive, this process should generate events periodically. The frequency is an integer number +of milliseconds between events.
The object associated with this process or coroutine.
If non-zero, the absolute time from the epoch (in milliseconds) that this process will trigger an event. +If zero, and the frequency is also zero, this process is called every idle loop.
A boolean flag. If true it indicates the process never returned or yielded during the event loop, +and will not be called again until it does so.
Wake up cron, and arrange for its event loop to be run during the next Idle cycle.
::cron::wake {I just did something important} @@ -254,24 +254,24 @@
Several utility commands are provided that are used internally within cron and for testing cron, but may or may not be useful in the general cases.
Return a clock time absolute to the epoch which falls on the next -border between one second and the next for the value of milleseconds
Return a clock time absolute to the epoch which falls on the next -border between one second and the next milleseconds in the future.
Return a clock time absolute to the epoch which falls exactly seconds in the future. If offset is given it may be positive or negative, and will shift the final time to before or after the second would flip.
Sets the internal clock for cron. This command will advance the time in 100ms increment, triggering events, until the internal time catches up with newtime.
-newtime is expressed in absolute milleseconds since the beginning of the epoch.
newtime is expressed in absolute milliseconds since the beginning of the epoch.
This document, and the package it describes, will undoubtedly contain bugs and other problems. Index: embedded/www/tcllib/files/modules/doctools/cvs.html ================================================================== --- embedded/www/tcllib/files/modules/doctools/cvs.html +++ embedded/www/tcllib/files/modules/doctools/cvs.html @@ -168,12 +168,11 @@ date, author of a log entry, and a comment for that entry, in this order, separated by commas.
The values are lists of the files the entry is touching.
] -The three arguments for this command are the same as the last three +
The three arguments for this command are the same as the last three arguments of the command ::doctools::cvs::scanLog. This command however expects them to be filled with information about one or more logs. It takes this information and converts it into a text in the format of a ChangeLog as accepted and generated by emacs. The constructed text is returned as the result of the command.
Remember that the whitespace is optional. The document
[manpage_begin NAME SECTION VERSION] -[see_also doctools_intro] -[see_also doctools_lang_cmdref] -[see_also doctools_lang_faq] -[see_also doctools_lang_syntax] -[keywords {doctools commands}] -[keywords {doctools language}] -[keywords {doctools markup}] -[keywords {doctools syntax}] -[keywords markup] -[keywords {semantic markup}] [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE] [require PACKAGE VERSION][require PACKAGE][description] [vset CATEGORY doctools] [include ../doctools2base/include/feedback.inc] [manpage_end] @@ -422,11 +412,11 @@ highlighting added. It shows their use within a block of text, as the arguments of a list item command (call), and our ability to nest them.... - [call [cmd arg_def] [arg type] [arg name]] [opt [arg mode]]] + [call [cmd arg_def] [arg type] [arg name] [opt [arg mode]]] Text structure. List element. Argument list. Automatically closes the previous list element. Specifies the data-[arg type] of the described argument of a command, its [arg name] and its i/o-[arg mode]. The latter is optional. ... Index: embedded/www/tcllib/files/modules/fumagic/cfront.html ================================================================== --- embedded/www/tcllib/files/modules/fumagic/cfront.html +++ embedded/www/tcllib/files/modules/fumagic/cfront.html @@ -139,13 +139,15 @@ the package fileutil::magic::cgen.
This command takes the paths of one or more files and directories and -compiles all the files, and the files in all the directories into a -single recognizer for all the file types specified in these files.
+This command takes the paths of one or more files and directories and compiles +all the files, and the files in all the directories into a single analyzer for +all the file types specified in these files. It returns a list whose first +item is a list per-file dictionaries of analyzer scripts and whose second item +is a list of analyzer commands.
All the files have to be in the format specified by magic(5).
The result of the command is a Tcl script containing the generated recognizer.
This command behaves like ::fileutil::magic::cfront::compile Index: embedded/www/tcllib/files/modules/fumagic/rtcore.html ================================================================== --- embedded/www/tcllib/files/modules/fumagic/rtcore.html +++ embedded/www/tcllib/files/modules/fumagic/rtcore.html @@ -123,76 +123,51 @@
This package provides the runtime core for file type recognition engines written in pure Tcl and is thus used by all other packages in -this module, i.e. the two frontend packages -fileutil::magic::mimetypes and -fileutil::magic::filetypes, and the two engine compiler +this module such as fileutil::magic::filetype and the two compiler packages fileutil::magic::cgen and fileutil::magic::cfront.
Shorthand for incr level.
Increment the level and perform related housekeeping
Shorthand for incr level -1.
This command initializes the runtime and prepares the file -filename for use by the system. -This command has to be invoked first, before any other command of this -package.
-The command returns the channel handle of the opened file as its -result.
This command closes the last file opened via -::fileutil::magic::rt::open and shuts the runtime down. -This command has to be invoked last, after the file has been dealt -with completely. -Afterward another invokation of ::fileutil::magic::rt::open is -required to process another file.
-This command returns the empty string as its result.
Decrement the level and perform related housekeeping
Create a new command which returns one description of the file each time it is +called, and a code of break when there are no more descriptions. +chan is the channel containing the data to describe. The channel +configuration is then managed as needed. +named is a dictionary of named tests, as generated by +fileutil::magic::cfront::compile. +test is a command prefix for a routine composed of the list of commands +as returned by fileutil::magic::cfront::compile.
This command marks the start of a magic file when debugging. It returns the empty string as its result.
This command returns the current result and stops processing.
-If msg is specified its text is added to the result before it is -returned. See ::fileutil::magic::rt::emit for the allowed -special character sequences.
This command returns the current result. -In contrast to ::fileutil::magic::rt::result processing -continues.
-If msg is specified its text is added to the result before it is -returned. See ::fileutil::magic::rt::emit for the allowed -special character sequences.
This command adds the text msg to the result buffer. The message may contain the following special character sequences. They will be replaced with buffered values before the message is added to the result. The command returns the empty string as its result.
Replaced with the last buffered string value.
Replaced with the last buffered numeric value.
See above.
This command fetches the numeric value with type from the -absolute location offset and returns it as its result. The -fetched value is further stored in the numeric buffer.
-If qual is specified it is considered to be a mask and applied -to the fetched value before it is stored and returned. It has to have -the form of a partial Tcl bit-wise expression, i.e.
-- & number --
For example:
-- Nv lelong 0 &0x8080ffff --
For the possible types see section NUMERIC TYPES.
This command behaves mostly like ::fileutil::magic::rt::Nv, -except that it compares the fetched and masked value against val -as specified with comp and returns the result of that -comparison.
-The argument comp has to contain one of Tcl's comparison -operators, and the comparison made will be
-- <val> <comp> <fetched-and-masked-value> +
Substitute one string if the file is executable, and +another string otherwise.
Produce an offset from where, relative to the cursor one level up. +Produce an offset from where, relative to the offset one level up.
A limited form of ::fileutile::magic::rt::N that only checks for +equality and can't be told to invert the test.
Fetch the numeric value with type from the absolute location +offset, compare it with expected using comp as the comparision +operator, and returns the result.
+The argument comp must be one of Tcl's comparison +operators.
++ <comp> <fetched-and-masked-value> <comp> <expected>
The special comparison operator x signals that no comparison should be done, or, in other words, that the fetched value will always match val.
This command behaves like ::fileutil::magic::rt::Nv, except that -it additionally remembers the location in the file after the fetch in -the calling context, for the current level, for later use by -::fileutil::magic::rt::R.
This command behaves like ::fileutil::magic::rt::N, except that -it additionally remembers the location in the file after the fetch in -the calling context, for the current, for later use by -::fileutil::magic::rt::R.
This command behaves like ::fileutil::magic::rt::N, except that -it fetches and compares strings, not numeric data. The fetched value -is also stored in the internal string buffer instead of the numeric -buffer.
This command behaves like ::fileutil::magic::rt::S, except that -it additionally remembers the location in the file after the fetch in -the calling context, for the current level, for later use by -::fileutil::magic::rt::R.
This command sets the current level in the calling context to +
Like ::fileutil::magic::rt::N except that it fetches and compares string +types , not numeric data.
Sets the current level in the calling context to newlevel. The command returns the empty string as its result.
This command handles base locations specified indirectly through the -contents of the inspected file. It returns the sum of delta and -the value of numeric type fetched from the absolute location -base.
-For the possible types see section NUMERIC TYPES.
This command handles base locations specified relative to the end of -the last field one level above.
-In other words, the command computes an absolute location in the file -based on the relative offset and returns it as its result. The -base the offset is added to is the last location remembered for the -level in the calling context.
Use a named test script at the current level.
Calculates an offset based on an initial offset and the provided modifiers.
Given an initial offset, calculates an offset relative to the cursor at the +next level up. The cursor is the position in the data one character after the +data extracted from the file one level up.
Add a level and use a named test script.
This module implements a web server, suitable for embedding in an @@ -210,357 +267,515 @@
Starting a web service requires starting a class of type httpd::server, and providing that server with one or more URIs to service, and httpd::reply derived classes to generate them.
-tool::define ::reply.hello { - method content {} { - my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>" - my puts "<h1>Hello World!</h1>" - my puts </BODY></HTML> - } -} -::docserver::server create HTTPD port 8015 myaddr 127.0.0.1 -HTTPD add_uri /* [list mixin reply.hello] --
This class is the root object of the webserver. It is responsible -for opening the socket and providing the initial connection negotiation.
-Build a new server object. ?port? is the port to listen on
Set the hander for a URI pattern. Information given in the dict is stored -in the data structure the dispatch method uses. If a field called -mixin is given, that class will be mixed into the reply object immediately -after construction.
Reply to an open socket. This method builds a coroutine to manage the remainder -of the connection. The coroutine's operations are driven by the Connect method.
This method reads HTTP headers, and then consults the dispatch method to -determine if the request is valid, and/or what kind of reply to generate. Under -normal cases, an object of class ::http::reply is created. -Fields the server are looking for in particular are: -class: A class to use instead of the server's own reply_class -mixin: A class to be mixed into the new object after construction. -All other fields are passed along to the http_info structure of the -reply object. -After the class is created and the mixin is mixed in, the server invokes the -reply objects dispatch method. This action passes control of the socket to -the reply object. The reply object manages the rest of the transaction, including -closing the socket.
Increment an internal counter.
Check open connections for a time out event.
Given a key/value list of information, return a data structure describing how -the server should reply.
Log an event. The input for args is free form. This method is intended -to be replaced by the user, and is a noop for a stock http::server object.
Return the actual port that httpd is listening on.
For the stock version, trim trailing /'s and *'s from a prefix. This -method can be replaced by the end user to perform any other transformations -needed for the application.
Open the socket listener.
Shut off the socket listener, and destroy any pending replies.
Return a template for the string page
Perform a search for the template that best matches page. This -can include local file searches, in-memory structures, or even -database lookups. The stock implementation simply looks for files -with a .tml or .html extension in the ?doc_root? directory.
Given a socket and an ip address, return true if this connection should -be terminated, or false if it should be allowed to continue. The stock -implementation always returns 0. This is intended for applications to -be able to implement black lists and/or provide security based on IP -address.
A class which shephards a request through the process of generating a -reply. -The socket associated with the reply is available at all times as the chan -variable. -The process of generating a reply begins with an httpd::server generating a -http::class object, mixing in a set of behaviors and then invoking the reply -object's dispatch method. -In normal operations the dispatch method:
-The bare module does have facilities to hose a files from a file system. Files that end in a .tml will be substituted in the style of Tclhttpd:
++<!-- hello.tml --> +[my html_header {Hello World!}] +Your Server is running. +<p> +The time is now [clock format [clock seconds]] +[my html_footer] ++
A complete example of an httpd server is in the /examples directory of Tcllib. It also show how to dispatch URIs to other processes via SCGI and HTTP proxies.
++cd ~/tcl/sandbox/tcllib +tclsh examples/httpd.tcl ++
Methods
+Converts a block of mime encoded text to a key/value list. If an exception is encountered, + the method will generate its own call to the error method, and immediately invoke + the output method to produce an error code and close the connection.
De-httpizes a string.
ancestors: httpd::mime
+A class which shephards a request through the process of generating a + reply. + The socket associated with the reply is available at all times as the chan + variable. + The process of generating a reply begins with an httpd::server generating a + http::class object, mixing in a set of behaviors and then invoking the reply + object's dispatch method. + In normal operations the dispatch method:
+Invokes the reset method for the object to populate default headers.
Invokes the HttpHeaders method to stream the MIME headers out of the socket
Invokes the request parse method to convert the stream of MIME headers into a -dict that can be read via the request method.
Stores the raw stream of MIME headers in the rawrequest variable of the object.
Invokes the content method for the object, generating an call to the error -method if an exception is raised.
Invokes the content method for the object, generating an call to the error + method if an exception is raised.
Invokes the output method for the object
The http::reply class and its derivatives maintain several variables as dictionaries -internally. Access to these dictionaries is managed through a dedicated ensemble. The -ensemble implements most of the same behaviors as the dict command. -Each ensemble implements the following methods above, beyond, or modifying standard dicts:
-Add element to a list stored in field, but only if it is not already present om the list.
Return the current contents of the data structure as a key/value list.
Return the value of the field field, or an empty string if it does not exist.
Return a key/value list of the default contents for this data structure.
Remove all instances of element from the list stored in field.
Replace the internal dict with the contents of keyvaluelist
Replace the internal dict with the default state.
Set the value of field to value.
Manages HTTP headers passed in by the server. -Ensemble Methods:
-Return the contents of this data structure as a netstring encoded block.
Managed data from MIME headers of the request.
-Replace the contents of the data structure with information encoded in a MIME -formatted block of text (string).
Manage the headers sent in the reply.
-Return the contents of this data structure as a MIME encoded block appropriate -for an HTTP response.
Terminate the transaction, and close the socket.
Stream MIME headers from the socket sock, stopping at an empty line. Returns -the stream as a block of text.
Take over control of the socket newsock, and store that as the chan variable -for the object. This method runs through all of the steps of reading HTTP headers, generating -content, and closing the connection. (See class writetup).
Generate an error message of the specified code, and display the message as the -reason for the exception. errorInfo is passed in from calls, but how or if it should be -displayed is a prerogative of the developer.
Generate the content for the reply. This method is intended to be replaced by the mixin. -Developers have the option of streaming output to a buffer via the puts method of the -reply, or simply populating the reply_body variable of the object. -The information returned by the content method is not interpreted in any way. -If an exception is thrown (via the error command in Tcl, for example) the caller will -auto-generate a 500 {Internal Error} message. -A typical implementation of content look like:
+Developers have the option of streaming output to a buffer via the puts method of the + reply, or simply populating the reply_body variable of the object. + The information returned by the content method is not interpreted in any way. + If an exception is thrown (via the error command in Tcl, for example) the caller will + auto-generate a 500 {Internal Error} message. + A typical implementation of content look like:
++ clay::define ::test::content.file { + superclass ::httpd::content.file + # Return a file + # Note: this is using the content.file mixin which looks for the reply_file variable + # and will auto-compute the Content-Type + method content {} { + my reset + set doc_root [my request get DOCUMENT_ROOT] + my variable reply_file + set reply_file [file join $doc_root index.html] + } + } + clay::define ::test::content.time { + # return the current system time + method content {} { + my variable reply_body + my reply set Content-Type text/plain + set reply_body [clock seconds] + } + } + clay::define ::test::content.echo { + method content {} { + my variable reply_body + my reply set Content-Type [my request get CONTENT_TYPE] + set reply_body [my PostData [my request get CONTENT_LENGTH]] + } + } + clay::define ::test::content.form_handler { + method content {} { + set form [my FormData] + my reply set Content-Type {text/html; charset=UTF-8} + my puts [my html_header {My Dynamic Page}] + my puts "<BODY>" + my puts "You Sent<p>" + my puts "<TABLE>" + foreach {f v} $form { + my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>" + } + my puts "</TABLE><p>" + my puts "Send some info:<p>" + my puts "<FORM action=/[my request get REQUEST_PATH] method POST>" + my puts "<TABLE>" + foreach field {name rank serial_number} { + set line "<TR><TH>$field</TH><TD><input name=\"$field\" " + if {[dict exists $form $field]} { + append line " value=\"[dict get $form $field]\""" + } + append line " /></TD></TR>" + my puts $line + } + my puts "</TABLE>" + my puts [my html footer] + } + } ++
Methods
+clean up on exit
Close channels opened by this object
Record a dispatch event
Accept the handoff from the server object of the socket + newsock and feed it the state datastate. + Fields the datastate are looking for in particular are:
+* mixin - A key/value list of slots and classes to be mixed into the + object prior to invoking Dispatch.
+* http - A key/value list of values to populate the object's request + ensemble
+All other fields are passed along to the clay structure of the object.
REPLACE ME: + This method is the "meat" of your application. + It writes to the result buffer via the "puts" method + and can tweak the headers via "clay put header_reply"
Formulate a standard HTTP status header from he string provided.
Generates the the HTTP reply, streams that reply back across chan, + and destroys the object.
For GET requests, converts the QUERY_DATA header into a key/value list. + For POST requests, reads the Post data and converts that information to + a key/value list for application/x-www-form-urlencoded posts. For multipart + posts, it composites all of the MIME headers of the post to a singular key/value + list, and provides MIME_* information as computed by the mime package, including + the MIME_TOKEN, which can be fed back into the mime package to read out the contents.
Stream length bytes from the chan socket, but only of the request is a + POST or PUSH. Returns an empty string otherwise.
Manage session data
Intended to be invoked from chan copy as a callback. This closes every channel + fed to it on the command line, and then destroys the object.
-tool::define ::test::content.file { - superclass ::httpd::content.file - # Return a file - # Note: this is using the content.file mixin which looks for the reply_file variable - # and will auto-compute the Content-Type - method content {} { - my reset - set doc_root [my http_info get doc_root] - my variable reply_file - set reply_file [file join $doc_root index.html] - } -} -tool::define ::test::content.time { - # return the current system time - method content {} { - my variable reply_body - my reply set Content-Type text/plain - set reply_body [clock seconds] - } -} -tool::define ::test::content.echo { - method content {} { - my variable reply_body - my reply set Content-Type [my request get CONTENT_TYPE] - set reply_body [my PostData [my request get CONTENT_LENGTH]] - } -} -tool::define ::test::content.form_handler { - method content {} { - set form [my FormData] - my reply set Content-Type {text/html; charset=UTF-8} - my puts [my html header {My Dynamic Page}] - my puts "<BODY>" - my puts "You Sent<p>" - my puts "<TABLE>" - foreach {f v} $form { - my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>" - } - my puts "</TABLE><p>" - my puts "Send some info:<p>" - my puts "<FORM action=/[my http_info get REQUEST_PATH] method POST>" - my puts "<TABLE>" - foreach field {name rank serial_number} { - set line "<TR><TH>$field</TH><TD><input name=\"$field\" " - if {[dict exists $form $field]} { - append line " value=\"[dict get $form $field]\""" - } - append line " /></TD></TR>" - my puts $line - } - my puts "</TABLE>" - my puts [my html footer] - } -} -+ ### + # Output the body + ### + chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096 + chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096 + if {$length} { + ### + # Send any POST/PUT/etc content + ### + chan copy $sock $chan -size $SIZE -command [info coroutine] + yield + } + catch {close $sock} + chan flush $chan +
Formulate a standard HTTP status header from he string provided.
For GET requests, converts the QUERY_DATA header into a key/value list. -For POST requests, reads the Post data and converts that information to -a key/value list for application/x-www-form-urlencoded posts. For multipart -posts, it composites all of the MIME headers of the post to a singular key/value -list, and provides MIME_* information as computed by the mime package, including -the MIME_TOKEN, which can be fed back into the mime package to read out the contents.
Converts a block of mime encoded text to a key/value list. If an exception is encountered, -the method will generate its own call to the error method, and immediately invoke -the output method to produce an error code and close the connection.
Generates the the HTTP reply, and streams that reply back across chan.
Stream length bytes from the chan socket, but only of the request is a -POST or PUSH. Returns an empty string otherwise.
Appends the value of string to the end of reply_body, as well as a trailing newline -character.
Clear the contents of the reply_body variable, and reset all headers in the reply -structure back to the defaults for this object.
Called from the http::server object which spawned this reply. Checks to see -if too much time has elapsed while waiting for data or generating a reply, and issues -a timeout error to the request if it has, as well as destroy the object and close the -chan socket.
Return the current system time in the format:
%a, %d %b %Y %T %Z
Intended to be invoked from chan copy as a callback. This closes every channel -fed to it on the command line, and then destroys the object.
-- ### - # Output the body - ### - chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096 - chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096 - if {$length} { - ### - # Send any POST/PUT/etc content - ### - chan copy $sock $chan -size $SIZE -command [info coroutine] - yield - } - catch {close $sock} - chan flush $chan --
De-httpizes a string.
The httpd module includes several ready to use implementations of content mixins -for common use cases. Options are passed in to the add_uri method of the server.
-An implementation to relay requests to process which will accept post data -streamed in vie stdin, and sent a reply streamed to stdout.
-Mandatory method to be replaced by the end user. If needed, activates the -process to proxy, and then returns a list of three values: -exec - The arguments to send to exec to fire off the responding process, minus the stdin/stdout redirection.
An implementation to deliver files from the local file system.
-The root directory on the local file system to be exposed via http.
The prefix of the URI portion to ignore when calculating relative file paths.
An implementation to relay requests to another HTTP server, and relay -the results back across the request channel.
-Mandatory method to be replaced by the end user. If needed, activates the -process to proxy, and then returns a list of three values: -proxyhost - The hostname where the proxy is located -proxyport - The port to connect to -proxyscript - A pre-amble block of text to send prior to the mirrored request
An implementation to relay requests to a server listening on a socket -expecting SCGI encoded requests, and relay -the results back across the request channel.
-Mandatory method to be replaced by the end user. If needed, activates the -process to proxy, and then returns a list of three values: -scgihost - The hostname where the scgi listener is located -scgiport - The port to connect to -scgiscript - The contents of the SCRIPT_NAME header to be sent
A placeholder for a future implementation to manage requests that can expect to be -promoted to a Websocket. Currently it is an empty class.
-The HTTP module also provides an SCGI server implementation, as well as an HTTP -implementation. To use the SCGI functions, create an object of the http::server.scgi -class instead of the http::server class.
-An modified http::reply implementation that understands how to deal with -netstring encoded headers.
-A modified http::server which is tailored to replying to request according to -the SCGI standard instead of the HTTP standard.
-Sean Woods
-ancestors: httpd::mime
+Methods
+Reply to an open socket. This method builds a coroutine to manage the remainder + of the connection. The coroutine's operations are driven by the Connect method.
This method reads HTTP headers, and then consults the dispatch method to + determine if the request is valid, and/or what kind of reply to generate. Under + normal cases, an object of class ::http::reply is created, and that class's + dispatch method. + This action passes control of the socket to + the reply object. The reply object manages the rest of the transaction, including + closing the socket.
Increment an internal counter.
Check open connections for a time out event.
Given a key/value list of information, return a data structure describing how + the server should reply.
Method dispatch method of last resort before returning a 404 NOT FOUND error. + The default behavior is to look for a file in DOCUMENT_ROOT which + matches the query.
Method dispatch method invoked prior to invoking methods implemented by plugins. + If this method returns a non-empty dictionary, that structure will be passed to + the reply. The default is an empty implementation.
Introspect and possibly modify a data structure destined for a reply. This + method is invoked before invoking Header methods implemented by plugins. + The default implementation is empty.
Introspect and possibly modify a data structure destined for a reply. This + method is built dynamically by the plugin method.
Convert an ip address to a host name. If the server/ reverse_dns flag + is false, this method simply returns the IP address back. + Internally, this method uses the dns module from tcllib.
Log an event. The input for args is free form. This method is intended + to be replaced by the user, and is a noop for a stock http::server object.
Incorporate behaviors from a plugin. + This method dynamically rebuilds the Dispatch and Headers + method. For every plugin, the server looks for the following entries in + clay plugin/:
+load - A script to invoke in the server's namespace during the plugin method invokation.
+dispatch - A script to stitch into the server's Dispatch method.
+headers - A script to stitch into the server's Headers method.
+thread - A script to stitch into the server's Thread_start method.
Return the actual port that httpd is listening on.
For the stock version, trim trailing /'s and *'s from a prefix. This + method can be replaced by the end user to perform any other transformations + needed for the application.
Open the socket listener.
Shut off the socket listener, and destroy any pending replies.
Return a template for the string page
Perform a search for the template that best matches page. This + can include local file searches, in-memory structures, or even + database lookups. The stock implementation simply looks for files + with a .tml or .html extension in the ?doc_root? directory.
Built by the plugin method. Called by the start method. Intended + to allow plugins to spawn worker threads.
Generate a GUUID. Used to ensure every request has a unique ID. + The default implementation is:
++ return [::uuid::uuid generate] ++
Given a socket and an ip address, return true if this connection should + be terminated, or false if it should be allowed to continue. The stock + implementation always returns 0. This is intended for applications to + be able to implement black lists and/or provide security based on IP + address.
Class to deliver Static content + When utilized, this class is fed a local filename + by the dispatcher
+Methods
+ +Methods
+ +ancestors: httpd::content.exec
+Return data from an proxy process
+Methods
+ +ancestors: httpd::content.proxy
+Methods
+For most CGI applications a directory list is vorboten
Upgrade a connection to a websocket
+httpd plugin template
+A rudimentary plugin that dispatches URLs from a dict + data structure
+Methods
+Implementation of the dispatcher
ancestors: httpd::reply
+Methods
+Methods
+A modified connection method that passes simple GET request to an object + and pulls data directly from the reply_body data variable in the object + Needed because memchan is bidirectional, and we can't seem to communicate that + the server is one side of the link and the reply is another
Sean Woods
+This document, and the package it describes, will undoubtedly contain bugs and other problems. Please report such in the category network of the Tcllib Trackers. Please also report any ideas for enhancements you may have for either @@ -571,14 +786,14 @@ inlined patches. Attachments can be made by going to the Edit form of the ticket immediately after its creation, and then using the left-most button in the secondary navigation bar.
TclOO, WWW, http, httpd, httpserver, services
+TclOO, WWW, http, httpd, httpserver, services
Networking
Copyright © 2018 Sean Woods <yoda@etoyoc.com>