Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 18.  TclHttpd Web Server

Application Direct URLs

The Application Direct domain implementation provides the simplest way to extend the Web server. It hides the details associated with query data, decoding URL paths, and returning results. All you do is define Tcl procedures that correspond to URLs. Their arguments are automatically matched up to the query data as shown in Example 13-3 on page 179. The Tcl procedures compute a string that is the result data, which is usually HTML. That's all there is to it.

The Direct_Url procedure defines a URL prefix and a corresponding Tcl command prefix. Any URL that begins with the URL prefix will be handled by a corresponding Tcl procedure that starts with the Tcl command prefix. This is shown in Example 18-2:

Example 18-2 Application 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\
      <input type=submit name=echo value='Echo Data'>\n\
proc Demo/time {{format "%H:%M:%S"}} {
   return [clock format [clock seconds] -format $format]
proc Demo/echo {args} {
   # Compute a page that echoes 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 18-2 defines /demo as an Application Direct URL domain that is implemented by procedures that begin with Demo. There are just three URLs defined:


The /demo page displays a hypertext link to the /demo/time page and a simple form that will be handled by the /demo/echo page. This page is static, and so there is just one return command in the procedure body. Each line of the string ends with:


This is just a formatting trick to let me indent each line in the procedure, but not have the line indented in the resulting string. Actually, the \-newline will be replaced by one space, so each line will be indented one space. You can leave those off and the page will display the same in the browser, but when you view the page source you'll see the indenting. Or you could not indent the lines in the string, but then your code looks somewhat odd.

The /demo/time procedure just returns the result of clock format. It doesn't even bother adding <html>, <head>, or <body> tags, which you can get away with in today's browsers. A simple result like this is also useful if you are using programs to fetch information via HTTP requests.

Using Query Data

The /demo/time procedure is defined with an optional format argument. If a format value is present in the query data, then it overrides the default value given in the procedure definition.

The /demo/echo procedure creates a table that shows its query data. Its args parameter gets filled in with a name-value list of all query data. You can have named parameters, named parameters with default values, and the args parameter in your application-direct URL procedures. The server automatically matches up incoming form values with the procedure declaration. For example, suppose you have an application direct procedure declared like this:

proc Demo/param { a b {c cdef} args} { body }

You could create an HTML form that had elements named a, b, and c, and specified /demo/param for the ACTION parameter of the FORM tag. Or you could type the following into your browser to embed the query data right into the URL:


In this case, when your procedure is called, a is 5, b is 7, c is red, and the args parameter becomes a list of:

d ~welch e {two words}

The %7e and the + are special codes for nonalphanumeric characters in the query data. Normally, this encoding is taken care of automatically by the Web browser when it gets data from a form and passes it to the Web server. However, if you type query data directly or format URLs with complex query data in them, then you need to think about the encoding. Use the Url_Encode procedure to encode URLs that you put into web pages.

If parameters are missing from the query data, they either get the default values from the procedure definition or the empty string. Consider this example:


In this case a is "", b is 5, c is cdef, and args is an empty list.

Returning Other Content Types

The default content type for application direct URLs is text/html. You can specify other content types by using a global variable with the same name as your procedure. (Yes, this is a crude way to craft an interface.) Example 18-3 shows part of the faces.tcl file that implements an interface to a database of picons ?personal icons ?that is organized by user and domain names. The idea is that the database contains images corresponding to your e-mail correspondents. The Faces_ByEmail procedure, which is not shown, looks up an appropriate image file. The application direct procedure is Faces/byemail, and it sets the global variable Faces/byemail to the correct value based on the filename extension. This value is used for the Content-Type header in the result part of the HTTP protocol.

Example 18-3 Alternate types for Application Direct URLs.
Direct_Url /faces Faces
proc Faces/byemail {email} {
   global Faces/byemail
   set filename [Faces_ByEmail $email]
   set Faces/byemail [Mtype $filename]
   set in [open $filename]
   fconfigure $in -translation binary
   set X [read $in]
   close $in
   return $X

      Previous section   Next section