Waitman Gobble, San Jose California
Hello, I am experimenting with the "Database as a Program" methodology described by D. Richard Hipp in the article SQLite and Tcl
At the moment my application consists of a short and simple main.tcl which decides which code segment to load from an sqlite3 database, executes the code and outputs the result.
I'm using the websh wrapper via mod_websh
Here is some sample code:
The app will process a request URI like http://example.com/main.ws3/hello Strategy: Create a directory on the machine to create all the snippet Tcl files, then package into SQLite database
package.tcl (package all tcl scripts in current directory into SQLite database)
load /usr/local/lib/sqlite3/libtclsqlite3.so Sqlite3 sqlite3 db task.db db eval {CREATE TABLE hd(path TEXT,src TEXT)} set files glob *.tcl foreach x $files { set fp open $x r set src read $fp close $fp set path /$x db eval {INSERT INTO hd VALUES ($path,$src)} } db close
hello.tcl (hello world example)
set content "Hello, World"
main.ws3 (process request in URI and load corresponding tcl code)
set fp open "layout.html" r set layout read $fp close $fp set path web::request PATH_INFO.tcl load /usr/local/lib/sqlite3/libtclsqlite3.so Sqlite3 sqlite3 db task.db set process db onecolumn {SELECT src FROM hd WHERE path=$path} eval $process db close set html regsub "<!--Content-->" $layout $content web::put $html
layout.html (a template)
<!doctype html> <html> <head> <title>boo</title> </head> <body> <!--Content--> </body> </html>
Experiments... Sample output (note, in development ;-)
#1 display CGI env info
http://creamy.mobi/test-series/testdt/main.ws3/testcmd
(ssl vars) https://creamy.mobi/test-series/testdt/main.ws3/testcmd
testcmd.tcl
set request web::request -names set combine join $request ", " set path web::request PATH_INFO set content "<h1>Request Info</h1> <p>${combine}</p> <p>${path}</p> "
#2 load and display static HTML file. The static page is specified in the query string (parameter pg). For test purposes adds the page request at the top. NOTE: You have to modify glob line in package.tcl, above, to also package html files in the current directory.
http://creamy.mobi/test-series/testdt/main.ws3/static?pg=contact
static.tcl (load html)
web::dispatch -postdata "" -cmd "" set page /web::param pg.html set content "<h1>$page</h1>" append content db onecolumn {SELECT src FROM hd WHERE path=$page}
contact.html
<h1>Contact</h1> <p>Contact us page</p> <p>(650) 396-7580</p>
#3 test file_mtime and file_md5
http://creamy.mobi/test-series/testdt/main.ws3/checkfile
package require md5 set file_mtime file mtime "layout.html" set file_md5 md5::md5 -hex -filename "layout.html" set content "<h1>Layout File</h1> <p>File Modification Check</p> <p>Last Modified: ${file_mtime}</p> <p>MD5: ${file_md5}</p> "
#4 test time/ip
http://creamy.mobi/test-series/testdt/main.ws3/hash
set time clock clicks set ip web::request REMOTE_ADDR append content "<p>time: $time $ip</p>"
Notes using websh/mod_websh
1. using mod_websh cwd is set to "/" (and not the directory in which the script is running)
2. when using mod_websh pkg download from site, also in freebsd /usr/ports/www/websh/ does not appear to log errors. download from svn and build seems to fix this problem (?)
sample build on freebsd
svn co http://svn.apache.org/repos/asf/tcl/websh/trunk websh cd websh/src/unix autoconf ./configure --with-tcl=/usr/local/lib/tcl8.5-threads \ --with-tclinclude=/usr/local/include/tcl8.5 \ --with-aprinclude=/usr/local/apache2/include/ \ --with-apuinclude=/usr/local/apache2/include/ \ --with-httpdinclude=/usr/local/apache2/include gmake && gmake install cp mod_websh* /usr/local/apache2/modules/ cp libwebsh85-threads.so.1 /usr/local/apache2/lib/
(vi httpd.conf)
LoadModule websh_module modules/mod_websh.so AddType application/x-httpd-tcl .ws3 AddHandler websh .ws3 WebshConfig conf/websh.conf
(see files in src dist:)
doc/mod_websh/conf/httpd.conf doc/mod_websh/conf/otherhandler.ws3 doc/mod_websh/conf/websh.conf doc/mod_websh/conf/htmlhandler.ws3