How AppWrap Works
This document is an overview of the operation of AppWrap. It describes what happens on each request received.
To illustrate the steps common to most requests, we first consider a generic request. We then look at specific AppWrap request types.
We provide a very high-level overview of an AppWrap request as it progresses through the Apache request cycle. We then provide a phase-by-phase, module by module description of how the request is processed.
The request is received by Apache. Several initialization handlers run including Apache::AppWrap::Doorknob which tries to assign a Response handler. Doorknob uses AppWrap administrative tables my_tables & my_defaults to make this determinatlon. An authentication (and potentially an authorization) handler is called before the response handler assigned by Doorknob. The response handler probably will invoke &paginator(), and is certain to invoke &Webify() to format the response for presentation. Lastly, the request is logged.
The incoming HTTP request will be a URI of the form ``http://<sitename>/<tablename[[/<command>][?arg=value]]''. (A fuller treatment of site URI may be found in the ``AppWrap Apache Configuration guide'' if/when it has been written.)
<sitename> is DNS name for this site, and may optionally contain additional path information. For example, ``http://www.foo.com/appwrap'', where sitename is ``www.foo.com''. <tablename> identifies to AppWrap the data being reguested, and is used as an index into the AppWrap administrative tables. <command> optionally instructs AppWrap how to act on the request. One or more <arg>, if present, filter the requested dataset or provides additional processing instructions
In the initialization phase all POST requests are converted to GET requests by Apache::AppWrap::POST2GET. This simplifies processing of CGI parameters and guery string arguments by later handlers.
Some site statistics are generated by Apache::AppWrap::Counter. Lastly Apache::AppWrap::Doorknob is called.
Doorknob is truly the entrance to AppWrap, performing several functions. It loads into memory data freqvently called by later handlers and subroutines. References to these data are stored in the %opts hash and passed to other handlers via the Apache request object.
Doorknob stores any query string arguments in $opts{args}. Path info from the URI is parsed; <tablename> and <command>, if present, is stored in %opts
From the meta-data tables Doorknob looks for a response handler assigned for this <tablename> in my_tables. If a handler is assigned it implies that <tablename> is a report rather than a data table. Doorknob assigns the handler, usually Apache::AppWrap::Catalyst, and exits.
If <tablename> is defined in my_tables but a handler is not, Doorknob assigns a handler based upon <command>. If <command> is not defined the default handler is Apache::AppWrap::List.
See related module documentation for more details.
AppWrap uses a plug-in strategy for Authentication. Site administrators can develop Authentication handlers to meet local needs. Currently 2 Authentication handlers are available: Apache::AppWrap::LDAP_subs and Apache::AuthAnon. Developers of Authentication Modules should consult module documentation.
In addition to satisfying Apache authentication requirements, modules should import %opts, and populate $opts{authed_email}.
AppWrap would welcome contributions of additional modules employing alternate Authentication methods. We believe it would be desirable to be able to customize existing (on CPAN) Apache Authentication modules, perhaps by subclassing one written using object oriented Perl (rather than modiying module code) , but we lack the in-house OO expertise to validate this belief. Help welcome.
The ``my_*'' tables provide configuration information to AppWrap handlers and subroutines. Config files in the filesystem probably could provide similar functionality. But we desired a degree of customizability and control that we couldn't get from flat files. Also, during initial development of AppWrap rarely did we have a fat connection to the server. That, and permissions issues rendered telnet sessions problematic. For these reasons, and with our discovery of the truly magnificent phpMyAdmin, storing and manipulating configuration directives in a MySQL database began to seem reasonable and possible. The meta-data tables are the result.
Each meta-data table includes an ``idnum'' column definition having a MySQL ``auto_increment'' attribute to assure the uniqueness of every record. Other columns are defined below.
Typically a subroutine or handler can provide an optional local value. If no local value then (as appropriate) table my_tables or my_columns is checked, before finally defaulting to the value provided in table my_defaults.
admin_name is the name of the directive.
admin_value is the value assigned to the directive.
description inbicates the purpose or context of the directive.
tablename is the <tablename> path component of the URI.
admin_name is the name of the directive.
admin_value is the value assigned to the directive.
tablename is the <tablename> path component of the URI.
func corresponds to the AppWrap phase handler to which this directive applies, such as ``display'', ``verify'' or ``focus''.
admin_name is the name of the directive.
admin_value is the value assigned to the directive.
tablename is the <tablename> path component of the URI.
col_name is the name of the column as defined in the MySQL table ``<tablename>''.
admin_name is the name of the directive.
admin_value is the value assigned to the directive.
A typical request may invoke one of several response handlers. All reports requests are handled by Apache::AppWrap::Catalyst. Each AppWrap phase has a Corresponding handler. And there are others.
The current situation is a bit of a muddle, and we are considering ways to resolve it. The goals of such an effort, were it to be undertaken, would be greater simplicity, improved code maintenance and administration, and inereased performance.
A possible way forward is to make Catalyst the sole response handler for the site. To achieve this requires rewriting the AppWrap phase handlers (List, Display, Focus, Generate_form, Verify and Confirm) as subroutines; same for any other response handlers (e. g., Chart_Counts, Calendar); removing the handler dispatching function in Doorknob (or perhaps revising to a subroutine dispatching function). These steps would comply with our goals for simplicity and maintenance, we aren't sure about the impact on performance. See Apache::AppWrap::Catalyst and other module documentation.
Most response handlers (or subroutine equivalents) call Apache::AppWrap::Pager::paginator() to structure requested data into a tabular format. paginator() accepts data and optional formatting arguments. If arguments are missing my_* tables are consulted. Users can, by clicking, sort and filter the resulting displayed data. See Apache::AppWrap::Pager module documentation.
All requests eventually are passed to Apache::AppWrap::Subs::Webiy() to be formatted for onscreen display. This approach has several advantages. All pages share a consistent look & feel. Changing screen layout requires editing a single sub. Put another way, an entirely different look & feel for the site can be achieved by rewriting Webify().
Presently Webify() is a called subroutine. Given its role, it might better be a handler, possibly a Cleanup or other late-in-the-request-cycle handler. Another issue for the ToDo list.
The final act in each reguest cycle is to log the request and related info in the log table (called 'accesses' by default.) This is done by a modified version of the CPAN module Apache::DBILogConfig.
Most AppWrap pages can be downloaded in spreadsheet friendly format by clicking a provided hyperlink. Even if the link is not provided you stand a good chance of getting lucky by simply appending ``/download'' to any URI (but before any query string args.)
When ``/download'' appears in the path info Doorknob sets the download flag ($opts{download_flag}) and sets the response hdndler to be Apache::AppWrap::Download.
Download runs thru the same steps as Apache::AppWrap::Catalyst, but only for Catalyst's ``body'' phase. The set download_flag tells well-behaved subroutines to return data with no HTML (as they otherwise might.)
Russell Lundberg <russell_lundberg@csi.com>
perl.