Toadhttpd is an effort to extend the Httpd (tcllib) module into a fully functioning web server, in the style of Tclhttpd. The project actually started as version 4.0 of Tclhttpd, but it became readily apparent that the new coroutine and Tcloo based dispatch engine was completely irreconcilable with the old interpreter/procs named just so method of the old system. Rather than put out an incompatible new version, hypnotoad decided it was better to just roll it out as a new project.
Principle development is published as a fossil repository: https://chiselapp.com/user/hypnotoad/repository/toadhttpd/index
Toadhttpd is designed to install a complete snapshot of all of the code it depends on into a file location. In that way a production environment can support multiple version of Toadhttpd running different generations of the software.
To install an instance of Toadhttpd:
# Clone and upack the fossil sources # Feel free to adjust the paths to your liking mkdir -p ~/tcl/fossil/ fossil clone https://chiselapp.com/user/hypnotoad/repository/toadhttpd ~/tcl/fossil/toadhttpd.fos mkdir -p ~/tcl/sandbox/toadhttpd cd ~/tcl/sandbox/toadhttpd fossil open ~/tcl/fossil/toadhttpd.fos # Make a directory to host your content from tclsh ~/tcl/sandbox/toadhttpd/make.tcl install ~/www/mysite cd ~/www/mysite ls htdocs httpd.tcl log modules plugin var ls htdocs hello.tml
To run the webserver:
tclsh httpd.tcl
If the file config.tcl is present in your directory, it will be read as a script during startup.
The default is to host the htdocs directory next to the httpd script as static content. However, like tclhttpd, you can embed template files that Tcl will perform substitutions on. The installer automatically drops in htdocs/hello.tml:
[my html_header {Hello World!}] Your Server is running. <p> The time is now [clock format [clock seconds]] [my html_footer]
You'll note the my statements in the template. The substitution is being performed inside the namespace of an httpd::reply instance. You can access information from the request via the my request method, and alter the outgoing headers via my reply. To institute a 301 redirect:
[my html_header {File has moved}] The file your were looking for [my request get REQUEST_URI] has moved. You will be redirected to: [### Manually generate a 303 reply set location /some/other/url my reply set Status 303 my reply set LOCATION $location return $location] a moment. <p> The time is now [clock format [clock seconds]] [my html_footer]
Sqlite based Logs and cache are accessible in the logs/ directory.
> ls log/ cache.sqlite log.sqlite > sqlite3 log/log.sqlite SQLite version 3.24.0 2018-06-04 19:24:41 Enter ".help" for usage hints. sqlite> .tables blackhole debug log session blackhole_journal journal log_info session_info sqlite> .schema log CREATE TABLE log ( time 'UNIXTIME' DEFAULT (now()), REMOTE_ADDR 'IPADDR', REMOTE_HOST 'HOSTNAME', REFERER 'URI', USER_AGENT 'STRING', HTTP_HOST 'HOSTNAME', REQUEST_URI 'URI', SESSION 'UUID' REFERENCES session DEFAULT(guuid()), COOKIE 'STRING', rowid INTEGER PRIMARY KEY AUTOINCREMENT, uuid STRING UNIQUE ); sqlite> select * from log; 1537370493|127.0.0.1|127.0.0.1|http://localhost:8015/|Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15|localhost:8015|/hello.tml|||5|d71a0fb6-0208-43f5-b468-58c797b3c901 sqlite>