[AMG]: This page provides detailed information about the design, implementation, and philosophy of the [Wibble] web server. <> ---- **Name** "Wibble" is similar in sound to "[Wub]", and according to the Jargon File [http://www.catb.org/jargon/html/W/wibble.html], it is one possible pronunciation of "[www]". ---- **Zone handlers** Zones are analogous to domains in Wub and [TclHttpd]. Zones are matched against the [URI] by prefix, with an important exception for directory names. I use the name "zone" instead of "domain" because I don't want any confusion with [DNS] domain names. Someday I may add support for virtual hosts via the Host: header, which means that DNS domain/host names will be included in zone names. Handlers can be stacked, so zones are defined by a combination of handlers which are executed in sequence. Each handler receives a request and response [dict]ionaries as its last two arguments. The request dictionary is augmented with configuration options and a few extra parameters. The request dictionary is derived from the HTTP request. The extra parameters indicate the match prefix and suffix, plus the (possible) filesystem path of the requested object. The response dictionary passed to the handler is a tentative response that the handler can update, replace, or simply ignore. The handler then returns using the [[nexthandler]] or [[sendresponse]] command. [[nexthandler]] takes an even number of parameters as arguments, which are alternating request/response pairs to pass to subsequent handlers. [[sendresponse]] takes only one parameter: the final response dict to send to the client. Zones also stack. For example, if no handlers for zone /foo return a response, then the handlers for / are tried. Just as the handlers within a zone must be specified in the order they are to be executed, the zones themselves must be specified in order of decreasing specificity. To inhibit this stacking behavior, be sure that a default handler is defined for the zone, e.g. '''notfound'''. The '''$wibble::zones''' variable defines the zones and their handlers. '''$wibble::zones''' is structured as a dict mapping from each zone prefix to its list of handlers. Each handler is a list of positional arguments (the first of which is the handler command name) and a list of key/value arguments which are merged into the request dictionary. The [[wibble::handle]] command is used to update this variable. Statically, the zone handlers form a stack or list. But dynamically (during program execution), the zone handlers can branch from a list into a tree, which is traversed in a breadth-first manner to search for a response to send to the client. The tree branches whenever [[nexthandler]] is given more than two arguments; each pair forms a new alternative handler stack operating on a modified request/response pair. When [[nexthandler]] is given zero arguments, the "node" is a leaf node, the tip of a dead branch; the request/response pair that was passed to the handler is removed from consideration. ---- **Request dictionary** ***Request dictionary entries received from client*** * '''socket''': The name of the Tcl [channel] that is connected to the client. * '''peerhost''': Network address of the client. * '''peerport''': TCP port number of the client. * '''method''': HTTP method (GET, PUT, POST, HEAD, etc.). * '''uri''': HTTP URI, including query string. * '''path''': Path of client-requested object, excluding query string. * '''protocol''': HTTP/1.0 or HTTP/1.1, whatever the client sent. * '''header''': Dictionary of HTTP header fields from the client. * '''rawheader''': List of HTTP header lines. * '''accept''': Dictionary mapping from Accept-X: headers to acceptable values, in descending qvalue order. * '''query''': Dictionary of query string elements. * '''rawquery''': Query string in text form. * '''post''': Dictionary of POST elements. * '''rawpost''': POST in text form. ***Extra parameters merged into request dictionary*** * '''port''': Local TCP server port number. * '''time''': Time of request, formatted with [[[clock format]]]. * '''rawtime''': Time of request in seconds since the epoch. * '''prefix''': Zone prefix name. * '''suffix''': Client-requested object path, sans prefix and query string. * '''fspath''': Object path with '''root''' option prepended. Only defined if '''root''' option is defined. ***Configuration options merged into request dictionary*** * '''root''': Filesystem directory corresponding to zone root directory. * '''indexfile''': Name of "index.html" file to append to directory requests. Support for configuration options varies between zone handlers. Zone handlers can also take positional configuration options by including them in the command argument to [[wibble::handle]], which is actually a [list]. ---- **Response dictionary** * '''status''': The numeric HTTP status to send. 200 is OK, 404 is Not Found, etc. * '''header''': Dictionary of HTTP header fields to send to the client. * '''content''': Message body to send to the client. * '''contentfile''': Name of a file containing the message body to send to the client. ---- **Predefined zone handlers** * '''vars''': Echo request dictionary plus any extra or optional arguments. * '''dirslash''': Redirect directory requests lacking a trailing slash. * '''indexfile''': Add '''indexfile''' to directory requests. * '''dirlist''': Serve directory listings. * '''template''': Compile *.tmpl files into *.script files. * '''script''': Execute *.script files. * '''static''': Serve static files (not directories). * '''notfound''': Send 404. <> Wibble