Hmmmm, the do does seem a little inefficient. I solved this problem in the
past by intiating a subrequest and changing the stack handler to
cgi-script right before running the cgi. something like this:
$subr = $r->lookup_uri($uri);
if($r->filename =~ /\.(cgi|pl)$)/o) {
$subr->handler('cgi-script');
}
$subr->run();
you might get into some trouble with headers if your cgi's return
http headers other than just Content-type like Location. If they don't go
ahead and add $r->send_http_header right before the run command. If they
do send other headers, you will need a patch for Apache.xs in the mod_perl
src. I have it and can give it to you if you are interested.
-amen
On Wed, 23 Aug 2000, Todd Finney wrote:
> Hi,
>
> I'm building a simple templating system. The major
> requirement of the system is that allow custom dynamic
> headers, footers, and toolbars based upon the identity of
> the user.
>
> The system so far works like this:
> - a user enters the site and logs in. The names
> of the user's default
> template, header, footer, and toolbar are placed
> into a cookie
> (via Apache::Session).
> - when the user requests a page, my handler
> intercepts that request, and
> looks at the user's cookie. Based upon the
> information in it, it grabs the
> appropriate template and components from the
> filesystem along with the
> requested page, rolls them together, and serves
> the result.
>
> A sample template file looks like this:
>
> <html>
> <head><title>Standard Template</title></head>
> <body bgcolor="#ffffff">
> <table width="650" cellspacing="0" cellpadding="0"
> border="0">
> <tr><td colspan="2" width="650" align="left"><!--
> Wrapper:header --><br></td></tr>
> <tr>
> <td width="150" align="left" valign="top"><!--
> Wrapper:toolbar --><br></td>
> <td width="500" align="left" valign="top"><!-- Content
> --><br></td></tr>
> <tr><td colspan="2" width="650" align="left"><!--
> Wrapper:footer --><br></td></tr>
> </table>
> </body></html>
>
> Component files, such as the header, footer and toolbar,
> are by convention self-contained html tables, ala
>
> # file components/tool/standard
>
> <table width="100%">
> <tr><td align="center"><a href="/wrapped/one.html">Link
> One</a><br></td></tr>
> <tr><td align="center"><a href="/wrapped/two.html">Link
> Two</a><br></td></tr>
> <tr><td align="center"><a href="/wrapped/three.html">Link
> Three</a><br></td></tr>
> <tr><td align="center"><a href="/wrapped/four.html">Link
> Four</a><br></td></tr>
> <tr><td align="center"><a href="/wrapped/five.html">Link
> Five</a><br></td></tr>
> <tr><td align="center"><a
> href="/wrapped/cgi-bin/test.pl">CGI</a><br></td></tr></table>
>
> I have a working version of this handler, but I think that
> there's a better way to do it, specifically the part that
> manages the content return part of the request. Static
> files are simple enough; I open the file and print it to
> STDOUT. Scripts, however, need to be handled
> differently. The way I'm doing it now works, but it
> strikes me as inefficient.
>
> package My::Wrapper;
>
> use strict;
> use Apache::Constants qw(:common DONE);
> use Apache::Log ();
>
> sub handler {
> my ( $r ) = shift;
> my ( $log ) = $r->log;
> $log->info("Wrapper: Inside Wrapper.");
> my ( $template_directory ) = "/www/html/templates/";
> my ( $components_directory ) =
> '/www/html/components/';
> #
> # these next four variables will come from the cookie,
> they are
> # set manually for now.
> #
> my ( $template ) = $template_directory.'standard';
> my ( $header ) =
> $components_directory.'head/'.'standard';
> my ( $toolbar ) =
> $components_directory.'tool/'.'standard';
> my ( $footer ) =
> $components_directory.'feet/'.'standard';
> $r->send_http_header;
> if ( -e $template ) {
> open( TEMPLATE, "$template" ) or die "Failed to
> open template $template: $!";
> while (<TEMPLATE>) {
> if ( $_ =~
> /(.*)<\!--\sWrapper:(\w+)\s-->(.*)/o ) {
> my ( $before ) = $1;
> my ( $component ) = $2;
> my ( $after ) = $3;
> my ( $name );
> $name = $header if $component eq 'header';
> $name = $toolbar if $component eq
> 'toolbar';
> $name = $footer if $component eq 'footer';
> print $before; &print_component($name);
> print $after;
> } elsif ( $_ =~ /(.*)<\!--\sContent\s-->(.*)/o
> ) {
> my ( $before ) = $1;
> my ( $after ) = $2;
> my ( $file ) = $r->filename;
> print $before;
> if ( -e $file ) {
> if ( $file =~ /(?:cgi|pl)$/ ) {
> $log->info("Wrapper: cgi script
> requested.");
> do $file;
> } else {
> $log->info("Wrapper: static file
> requested.");
> open(CONTENT, "$file" ) or die
> "Failed to open content file $file: $!";
> while (<CONTENT>) {
> print $_;
> }
> close(CONTENT);
> }
> }
> print $after;
> } else {
> print $_;
> }
> }
> close( TEMPLATE );
> }
> $log->info("Wrapper: Exiting Wrapper.");
> return DONE;
> }
>
> sub print_component {
> my ( $component ) = shift;
> if ( -e $component ) {
> open(IN, "$component" ) or die "Failed to open
> component $component: $!";
> while (<IN>) {
> print $_;
> }
> close(IN);
> return 1;
> } else {
> print "Failed to open component $component.";
> return 0;
> }
> }
> 1;
> __END__
>
> I have experimented with various ways of handling this,
> such as printing a redirect, but this is the only way I
> could get it to work. I suspect that there is a better way
> to do it. I'd rather not `` the script, because of
> efficiency worries and the desire to maintain some process
> environment variables used in our authentication systems.
>
> Thanks a bunch,
> Todd
>
>
>