(According to https://tcl.apache.org/ the mod_tcl and Websh projects are no longer supported (2023). Rivet is still developed and supported.)
Notes on a talk given by Olly Stephens at Tcl2008.
mod_tcl is one of three technologies available through http://tcl.apache.org/ . All three added to support Apache's httpd daemon for authoring dynamic web pages in Tcl. All three can be embedded inside the Apache server itself as a persistent interpreter. The others, Websh, and Rivet focus on providing a good framework for generating HTML pages (classic way to mix HTML and a dynamic language). mod_tcl is a little different. mod_tcl focuses on exposing the guts of the request workflow to Tcl. Not as feature rich as the others for page generation, but capable of doing other things too.
mod_tcl is dangerously close to the deadpool. No major releases or code changes since 2002 (version 1.0). However, COMPANY: ARM use mod_tcl in one of our core customer facing websites. Used to manage the delivery of large datasets to partners. Over the years he's tweaked changed, refined the code enough that it is almost a complete rewrite. Lots of additional functionality. "About time I contributed it back." (This talk is the first step of that.)
Apache request flow:
Apache Directives
TclTranslateHandler translate tcllib/mapper.tcl TclLogHandler ::myapp::log_access TclResponseHandler page
Example 1: response handling
conf/httpd.conf:
<FilesMatch "\.tcl$"> SetHandler tcl-script TclResponseHandler response </FilesMatch>
htdocs/test.tcl:
proc response {} { apache::request content_type text/html apache::send_http_header apache::rputs "<html>" ... apache::rputs "</html>" return $::apache::OK }
Example 2: authentication
conf/httpd.conf:
<Location /secret> AuthType Basic AuthName "My Secret Stuff" Require valid-user TclAuthenHandler authen tcllib/auth/handlers.tcl TclAuthzHandler authz tcllib/auth/handlers.tcl </Location>
tcllib/auth/handlers.tcl:
proc authen {} { foreach {rc pw} [apache::get_basic_auth_pw] break if {$rc != $::apache::OK} {return $rc} if {$pw eq [apache::request user]} {return $::apache::OK} apache::note_basic_auth_failure return $::apache::HTTP_FORBIDDEN } proc authz {} { if {[apache::request user] eq "olly"} { return $::apache::OK } else {return $::apache::HTTP_FORBIDDEN} }
Additional modules:
Example 3: uploading via PUT
conf/httpd.conf:
<Location /uploads> TclTransHandler translate tcllib/putfile.tcl TclResponseHandler response </Location>
tcllib/putfile.tcl:
proc translate {} { apache::request filename tcllib/putfile.tcl return $::apache::OK } proc response {} { if {[apache::request method] ne "PUT"} { error "not a PUT request" } set nm [file join $::TMPDIR [file tail [apache::request uri]]] set fd [open $nm w] set sz [fcopy stdin $fd] close $fp apache::request content_type text/plain puts "uplaoded $nm ($sz bytes)" return $::apache::OK }
Example 4: downloading (ranges)
conf/httpd.conf:
<Location /downloads> TclTransHandler translate tcllib/getfile.tcl </Location>
tcllib/getfile.tcl:
proc translate {} { foreach {key fnm typ} [spool_file [apache::request uri]] break apache::request filename $fnm apache::handler type [namespace code "set_type $typ"] apache::handler log [namespace code "log_dnld $key [clock sec]"] return $::apache::OK } proc set_type {typ} { apache::request content_Type $typ } proc log_dnld {key start} { log_download $key [apache::request bytes_sent] \ [expr [clock seconds] - $start] }
(Note: Examples are (per Olly) abbreviated untested samples to fit within the constraints of a single slide, and also subject to my transcription errors--MC.)
Interpreter Handling:
Implementation challenges? APR tables. They are like dictionaries, but can have duplicate keys. They are used a lot for Apache structures so needed an interface.
Current status: