| [ Team LiB ] |
|
Domain HandlersYou can implement new kinds of domains that provide your own interpretation of a URL. This is the most flexible interface available to extend the Web server. You provide a callback that is invoked to handle every request in a domain, or subtree, of the URL hierarchy. The callback interprets the URL, computes the page content, and returns the data using routines from the Httpd module. Example 18-2 defines a simple domain that always returns the same page to every request. The domain is registered with the Url_PrefixInstall command. The arguments to Url_PrefixInstall are the URL prefix and a callback that is called to handle all URLs that match that prefix. In the example, all URLs that have the prefix /simple are dispatched to the SimpleDomain procedure. The SimpleDomain handler illustrates several properties of domain handlers. The sock and suffix arguments to SimpleDomain are appended by Url_Dispatch when it invokes the domain handler. The sock is the socket connection to the client. The suffix parameter is the part of the URL after the prefix. For example, if the server receives a request for the URL /simple/page, then the prefix is /simple and the suffix is /page. The prefix argument is defined when the callback is registered with Url_PrefixInstall. You can specify whatever information you need to pass to the domain handler. In this simple example, we probably don't need the prefix, but if you implement several different URL domains with the same handler, then you can pass in the prefix to distinguish them. Example 18-2 A 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 connection state
append html "<h1>Connection State</h1>"
append html [html::tableFromArray data border=1]
# Display query data
if {[info exist data(query)]} {
append html "<h1>Query Data</h1>\n"
append html [html::tableFromList [ncgi::nvlist] border=1]
}
Httpd_ReturnData $sock text/html $html
}
Connection State and Query DataThe sock parameter is a handle on the socket connection to the remote client. This variable is also used to name a state variable that the Httpd module maintains about the connection. The name of the state array is Httpd$sock. In some cases, you may need access to this information, and the standard idiom is to use upvar to get a more convenient name for this array (i.e., data): upvar #0 Httpd$sock data The html and ncgi PackagesThe html package provides many procedures useful for generating fragments of HTML. The html::tableFromArray procedure is used to dump out the connection state in the data array. Its cousin, html::tableFromList, is used to dump out the query data. The query data is obtained with the ncgi::nvlist procedure. TclHttpd initializes the ncgi module so you can use ncgi::nvlist, ncgi::value, and other procedures to access query data in your domain handlers. Note: it is not necessary to call ncgi::parse as you would from a CGI script. The html package has some other features, which are described later, that are very useful when generating HTML forms. These packages are part of the Standard Tcl Library, tcllib, which can be found along with Tcl and TclHttpd. Returning ResultsFinally, once the page has been computed, the Httpd_ReturnData procedure is used to return the page to the client. This takes care of the HTTP protocol as well as returning the data. There are three related procedures, Httpd_ReturnFile, Httpd_Error, and Httpd_Redirect. These are summarized in Table 18-1 on page 277. |
| [ Team LiB ] |
|