httcld is a very small HTTP server with an embedded TCL (http://www.tcl.tk/) interpreter. In addition to static .html files, it serves .htcl files, which are HTML with embedded tcl code. The tcl is executed on the server, and the resulting output is embedded in the stream sent back to the client. In addition, variables in the tcl namespace may be set and retrieved directly, say by an AJAX script.
The idea for this server came out of a need to have a flexible, fast, but very lightweight backend to support a GUI on an embedded platform. I also wanted efficient support for a more dynamic AJAX-like interface, but the existing backends were much too big for the box. Apache and it's modules took too much memory and storage space, Ruby and Rails likewise. Java was right out.
Thus was born the idea of a specialized HTTP server that could update a very dynamic UI without any more CPU overhead than necessary. Along the way, I decided that it would be nice if I could make the web pages in the UI smarter. This led to the embedded .htcl format.
www.gnu.org/software/libmicrohttpd Version 0.4.0pre1
andwww.tcl.tk Version 8.5
The server also directly contains hash table code from David Crawshaw http://www.zentus.com/c/hash.html
In addition, some of the examples use the Prototype Javascript library from http://www.prototypejs.org/
The README file in the source distribution has complete information on building, configuring, and operating the server.
Here's an example .htcl file, illustrating embedded tcl and AJAX support (this is protoclock3.htcl in the examples/ directory):
<!-- httcld 1.1 example This is an example of an Ajax page that calls a tcl proc named "getsysdata" to periodically update multiple items on a page. The proc is created in the tcl script block below, and is called by the Javascript code further down. This proc returns multiple items in a JSON string, reducing the number of HTTP calls needed to update a page. --> <tcl> # this tcl code runs on the server # return the current server time in JSON format proc jclock {} { return [clock format [clock seconds] -format "\"hour\": \"%H\", \"min\": \"%M\", \"sec\": \"%S\" " ] } # return the system load average in JSON format proc jload {} { # if the native.so library was is available if {$::native_loaded} { # get the load from the system return " \"load\": \"[nat_sysload]\" " } else { # fake a return value return " \"load\": \"0 0 0\" " } } # return a JSON string with the time and system load proc getsysdata {} { # send JSON output puts "{\"jval\": { [jclock] , [jload] }}" } # log that we loaded this page log_msg "$argv0 loaded" </tcl> <html> <head> <title> Prototype-based clock </title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <meta http-equiv="pragma" content="no-cache"> <!-- load the prototype library here --> <script type="text/javascript" src="js/prototype.js"></script> </head> <body> <!-- here we create the page that the user sees. Each element returned from the /tcl/ proc is placed in it's corresponding div --> Server time:<br> <table> <tr> <td>hr:</td><td><div id="hour" class=""></div></td> <td>min:</td><td><div id="min" class=""></div></td> <td>sec:</td><td><div id="sec" class=""></div></td> </tr> </table> <table> <tr> <td>System Load Average: </td><td><div id="load" class=""></div></td><td></td> </tr> </table> <br> <div id="debug" class=""> <!-- client-side script --> <script type="text/javascript"> // this Javascript code runs in the browser // url that activate the /tcl/ proc defined above var url = '/tcl/proc?name=getsysdata'; // this sets up Prototype to periodically make the Ajax request to the // server, and evaluate the JSON response. The divs in the user page // above are filled in with the values fron the JSON response. // // Note: This function starts on page load, and may be stopped at any // time. But once stopped, it can only be restarted by reloading the // page. var Ajc = new PeriodicalExecuter(function(pe) { new Ajax.Request(url, { method: 'get', evalJSON: 'force', onSuccess: function(transport) { // get the JSON output var json = transport.responseJSON; // now go fill in the divs above for (i in json.jval) { $(i).innerHTML = json.jval[i]; } } }); }, 1); // update every 1 second </script> <!-- give it a control button --> <input type="button" onClick="Ajc.stop();" value="Stop Update"> <body> </html>
This page, once loaded and started, looks like this in the browser:
Everything within the <tcl> </tcl> tags is executed on the server, the rest is passed unchanged to the browser.
Notice that this example has both server-side and client-side code in the same file. This is one way to organize your code, but your don't have to do it this way. It's perfectly acceptable to group all your server-side tcl code in the init script, and your client-side Javascript in .html files like you normally would.
I used Prototype in the examples created so far. There's no reason that it wouldn't work just as well with Dojo, script.aculo.us, OAT, qooxdoo, or any other AJAX framework. Or, you don't even need a browser at all. Say you wanted a console TUI (thxt-based UI). You could write a shell script using curl to query server values using the /tcl/ URL handler, and dialog to present them to the user. Simple.
There are the usual forums at Sourceforge - feel free to post questions or suggestions. Or drop me an email if you have any comments. I intend to improve the server and add features as I need them, but suggestions are always welcome.
Copyright (C) 2008 Mark Anacker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Last updated: 12/25/2008 | Project Web Hosted by |