The Tclhttpd Web Server
Total Page:16
File Type:pdf, Size:1020Kb
The TclHttpd Web Server Brent Welch <[email protected]> Scriptics Corporation Abstract • Static pages. As a "normal" web server, you can serve static documents that describe your This paper describes TclHttpd, a web server built application. entirely in Tcl. The web server can be used as a • Domain handlers. You can arrange for all stand-alone server or it can be embedded into URL requests in a section of your web site to applications to web-enable them. TclHttpd provides be handled by your application. This is a very a Tcl+HTML template facility that is useful for general interface where you interpret what the maintaining site-wide look and feel, and an appli- URL means and what sort of pages to return cation-direct URL that invokes a Tcl procedure in to each request. For example, an application. This paper describes the architec- http://www.scriptics.com/resource is ture of the application and relates our experience implemented this way. The URL past using the system to host www.scriptics.com. /resource selects an index in a simple data- base, and the server returns a page describing the pages under that index. Introduction • Application-Direct URLs. This is a domain TclHttpd started out as about 175 lines of Tcl that handler that maps URLs onto Tcl procedures. could serve up HTML pages and images. The Tcl The form query data that is part of the HTTP GET or POST request is automatically socket and I/O commands make this easy. Of course, there are lots of features in web servers like mapped onto the parameters of the applica- Apache or Netscape that were not present in the tion-direct procedure. The procedure simply first prototype. Steve Uhler took my prototype, computes the page as its return value. This is refined the HTTP handling, and aimed to keep the an elegant and efficient alternative to the CGI basic server under 250 lines. I went the other direc- interface. For example, in TclHttpd the URLs tion, setting up a modular architecture, adding in under /status report various statistics about features found in other web servers, and adding the web server’s operation. some interesting ways to connect TclHttpd to Tcl • Document handlers. You can define a Tcl pro- applications. cedure that handles all files of a particular type. For example, the server has a handler Today TclHttpd is used both as a general-purpose for CGI scripts, HTML files, image maps, Web server, and as a framework for building server and HTML+Tcl template files. applications. It implements www.scriptics.com, • HTML+Tcl Templates. These are web pages including the Tcl Resource Center and Scriptics’ that mix Tcl and HTML markup. The server electronic commerce facilities. It is also built into replaces the Tcl using the subst command several commercial applications such as license and returns the result. The server can cache servers and mail spam filters. the result in a regular HTML file to avoid the overhead of template processing on future requests. Templates are a great way to main- Integrating with TclHttpd tain common look and feel to a family of web TclHttpd is interesting because, as a Tcl script, it is pages, as well as to implement more easy to add to your application. Suddenly your advanced dynamic HTML features like self- application has an interface that is accessible to checking forms. Web browsers in your company’s intranet or the global Internet. The Web server provides several ways you can connect it to your application: TclHttpd Architecture Domain Handlers Figure 1 shows the basic components of the server. You can implement new kinds of domains that pro- At the core is the Httpd module, which implements vide your own interpretation of a URL. This is the the server side of the HTTP protocol. This module most flexible interface available to extend the web manages network requests, dispatches them to the server. You provide a callback that is invoked to Url module, and provides routines used to return handle every request in a domain, or subtree, of the the results to requests. The Url module divides the URL hierarchy. The callback interprets the URL, web site into domains, which are subtrees of the using routines from the Httpd module. URL hierarchy provided by the server. The idea is Example 1 defines a simple domain that always that different domains may have completely differ- returns the same page to every request. The domain ent implementations. For example, the Document is registered with the Url_PrefixInstall com- domain maps its URLs into files and directories on mand. The arguments to Url_PrefixInstall are your hard disk, while the Application-Direct the URL prefix and a callback that is called to han- domain maps URLs into Tcl procedure calls within dle all URLs that match that prefix. In the example, your application. The CGI domain maps URLs onto all URLs that have the prefix /simple are dis- other programs that compute web pages. patched to the SimpleDomain procedure. File Other System Applications Your Application Templates Application Direct CGI Documents Url Httpd TclHttpd Figure 1 The dotted box represents one application that embeds TclHttpd. Document templates and Application Direct URLs provide direct connections from an HTTP request to your applica- tion. Example 1A simple URL domain. Url_PrefixInstall /simple [list SimpleDomain /simple] proc SimpleDomain {prefix sock suffix} { upvar #0 Httpd$sock data # Generate page header set html "<title>A simple page</title>\n" append html "<h1>$prefix$suffix</h1>\n" append html "<h1>Date and Time</h1>\n" append html [clock format [clock seconds]] # Display query data if {[info exist data(query)]} { append html "<h1>Query Data</h1>\n" append html "<table>\n" foreach {name value} [Url_DecodeQuery $data(query)] { append html "<tr><td>$name</td>\n" append html "<td>$value</td></tr>\n" } append html "</table>\n" } Httpd_ReturnData $sock text/html $html } The SimpleDomain handler illustrates several prop- cedure is used to decode the data into a list of names erties of domain handlers. The sock and suffix and values. arguments to SimpleDomain are appended by Finally, once the page has been computed, the Url_Dispatch when it invokes the domain handler. Httpd_ReturnData procedure is used to return the The suffix parameter is the part of the URL after page to the client. This takes care of the HTTP pro- the prefix. The prefix is passed in as part of the tocol as well as returning the data. There are three callback definition so the domain handler can recre- related procedures, Httpd_ReturnFile, ate the complete URL. For example, if the server Httpd_Error, and Httpd_Redirect. receives a request for the url /simple/page, then the prefix is /simple, the suffix is /page. The sock parameter is a handle on the socket con- Application Direct URLs nection to the remote client. This variable is also The Application Direct domain implementation used to name a state variable that the Httpd module maintains about the connection. The name of the provides the simplest way to extend the web server. It hides the details associated with query data, state array is Httpd$sock, and SimpleDomain uses decoding URL paths, and returning results. All you upvar to get a more convenient name for this array do is define Tcl procedures that correspond to (i.e., data): URLs. Their arguments are automatically matched upvar #0 Httpd$sock data up to the query data. The Tcl procedures compute a The only module in the server that uses the socket string that is the result data, which is usually handle directly is the Httpd module. The rest of the HTML. That’s all there is to it. code treats $sock as an opaque handle, and uses the upvar trick to map that handle into a locally acces- The Direct_Url procedure defines a URL prefix sible array. and a corresponding Tcl command prefix. Any URL that begins with the URL prefix will be han- An important element of the state array is the query dled by a corresponding Tcl procedure that starts data, . This is the information that data(query) with the Tcl command prefix. This is shown in comes from HTML forms. The query data arrives in Example 2: an encoded format, and the Url_DecodeQuery pro- Example 2Application Direct URLs Direct_Url /demo Demo proc Demo {} { return "<html><head><title>Demo page</title></head>\n\ <body><h1>Demo page</h1>\n\ <a href=/demo/time>What time is it?</a>\n\ <form action=/demo/echo>\n\ Data: <input type=text name=data>\n\ <br>\n\ <input type=submit name=echo value=’Echo Data’>\n\ </form>\n\ </body></html>" } proc Demo/time {{format "%H:%M:%S"}} { return [clock format [clock seconds] -format $format] } proc Demo/echo {args} { # Compute a page that echos the query data set html "<head><title>Echo</title></head>\n" append html "<body><table>\n" foreach {name value} $args { append html "<tr><td>$name</td><td>$value</td></tr>\n" } append html "</tr></table>\n" return $html } Example 2 defines /demo as an Application Direct Using Query Data URL domain that is implemented by procedures The /demo/echo procedure creates a table that that begin with Demo. There are just three URLs defined: shows its query data. Its args parameter gets filled in with a name-value list of all query data. You can /demo have named parameters, named parameters with /demo/time default values, and the args parameter in your /demo/echo application-direct URL procedures. The server The /demo page displays a hypertext link to the automatically matches up incoming form values /demo/time page, and a simple form that will be with the procedure declaration.