In case you care, the way I decided to handle the header_add and header_props compatibility was to actually just use CGI. C::A defines the interface as CGI compatible and the only way to really keep it that way is to use CGI. So if you use header_add and header_props then it will require CGI and use it to generate the headers. But I also encouraged everyone to use the Apache way of doing things for now on.
Please test it out and give more feedback. I'll take it and put together a full CPAN release with tests, etc in a couple of days.
Thanks again -- Michael Peters Developer Plus Three, LP
NAME
CGI::Application::Plugin::Apache - Allow CGI::Application to use
Apache::* modules without interferenceSYNOPSIS
use base 'CGI::Application';
use CGI::Application::Plugin::Apache qw(:all);# then later we join our hero in a run mode...
sub mode1 {
my $self = shift;
my $q = $self->query(); # $q is an Apache::Request obj not a CGI.pm obj
# do some stuff
# now we can bake a cookie using Apache::Cookie without interference
$cookie = Apache::Cookie->new(
$q,
-name => 'foo',
-value => 'bar',
-expires => '+2h',
);
$cookie->bake;
# now let's play with the content_type and other headers
$q->content_type('text/plain');
$q->header_out('MyHeader' => 'MyValue'); # do other stuff
return $content;
}1;
DESCRIPTION
This plugin helps to try and fix some of the annoyances of using
CGI::Application in a pure mod_perl environment. CGI::Application
assumes that you use CGI.pm, but I wanted to avoid it's bloat and have
access to the performance of the Apache::* modules so along came this
plugin. At the current moment it only does two things:Use Apache::Request as the "$self->query" object thus avoiding the
creation of the CGI.pm object.
Override the way CGI::Application creates and prints it's HTTP headers.
Since it was using CGI.pm's "header()" and "redirect()" method's we
needed an alternative. So now we use the "Apache->send_http_header()"
method. This has a few additional benefits other than just not using
CGI.pm. It means that we can use other Apache::* modules that might also
create outgoing headers (e.g. Apache::Cookie) without CGI::Application
clobbering them.
EXPORTED METHODS
This module uses Exporter to provide methods to your application module.
Most of the time you will never actually use these methods since they
are used by CGI::Application itself, but I figured you'd like to know
what's going on.
No methods are exported by default. It is up to you to pick and choose,
but please choose wisely. You can import all of the methods by using:use CGI::Application::Plugin::Apache qw(:all);
It is recommended that you import all of them since some methods will
require others.. but the choice is yours. For instance, if you want to
override any method then you may not want to import it from here.handler()
This method gives your application the ability to run as a straight
mod_perl handler. It simply creates an instance of you application and
then runs it (using "$app->new()" and "$app->run()"). It does not pass
any arguments into either method. It then returns an
"Apache::Constants::OK" value. If you need anything more than this,
please feel free to not import this method and write your own. You could
do it like this:
package MyApp;
use base 'CGI::Application';
use CGI::Application::Plugin::Apache qw(:all !handler); sub handler {
# do what every you want here
}cgiapp_get_query()
This overrides CGI:App's method for retrieving the query object. This is
the standard way of using something other than CGI.pm so it's no
surprise that we use it here. It simply creates and returns a new
Apache::Request object from "Apache->request".
_send_headers()
I didn't like the idea of exporting this private method (I'd rather
think it was a 'protected' not 'private) but right now it's the only way
to have any say in how the HTTP headers are created. This method will
only recognize the following values set by the "$self->header_type()"
method:
* header
If you have previously called "header_props()" or "header_add()" in
your code then it mean we have to use CGI.pm to actually create the
headers. If you haven't then we use Apache to do it. See "HTTP
Headers" for more details. * none
The means we don't send any headers and it's up to the user to send
them however they want. * redirect
This should function just the same as CGI::Application normally
does, except that it will try to use Apache to send the headers and
not CGI.pm.HTTP Headers
Cookies
HTTP headers (and hence HTTP cookies) are now not created with
"header_add()" or "header_props()". Instead use Apache::Cookie for
cookies and anything you want for additional header manipulation. Redirects
You can still do the following to perform an HTTP redirect $self->header_props( uri => $some_url);
$self->header_type('redirect');
return '';But now we encourage you to do the following
$self->query->header_out(Location => $some_url);
$self->query->status(REDIRECT);
return '';But it's really up to you.
CAVEATS
Upon using this module you completely leave behind the world of CGI.pm.
Don't look back or you might turn into a pillar of salt. You will have
to look at and read the docs of the Apache::* modules. But don't worry,
they are really easy to use and were designed to mimic the interface of
CGI.pm.If you are trying to use this module but don't want to have to change
your previous code that uses "header_props()" or "header_add()" then we
try to help you out. We do this by actually requiring CGI and then
passing those values along. We recommend that you learn the mod_perl way
of baking cookies and setting outgoing header values. If you still want
to use "header_props()" or "header_add()" remeber that it will cause a
performance hit.
Also it's important to note that you can't combine both methods. This
means you can't combine calls of "header_props()" or "header_add()" with
"header_out" or "status" within the same sequence of events.
AUTHOR
Michael Peters <[EMAIL PROTECTED]>SEE ALSO
* CGI::Application
* Apache
* Apache::Registry
* Apache::CookieLICENSE
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.package CGI::Application::Plugin::Apache; use strict; use base 'Exporter'; use Apache; use Apache::Request; use Apache::Reload; use Apache::Constants qw(:common :response); use Carp;
$CGI::Application::Plugin::Apache::VERSION = 0.02;
use vars qw(@EXPORT_OK %EXPORT_TAGS);
@EXPORT_OK = qw(handler cgiapp_get_query _send_headers);
%EXPORT_TAGS = (all => [EMAIL PROTECTED]);
sub handler ($$) {
my ($self, $r) = @_;
my $app = $self->new();
$app->run();
return OK;
}
sub cgiapp_get_query {
my $self = shift;
my $apr = Apache::Request->new( Apache->request() );
return $apr;
}
sub _send_headers {
my $self = shift;
my $header_type = $self->header_type();
#if we are redirecting try and do it with header_out
if ($header_type eq 'redirect') {
my %props = $self->header_props();
my $url = '';
foreach my $key (keys %props) {
$url = $props{$key}
if($key =~ /uri$/i);
}
#if we actually have a url
if($url) {
$self->query->header_out(Location => $url);
$self->query->status(REDIRECT);
$self->query->send_http_header()
} else {
#else they are trying to redirect with giving a destination
croak("header_type of 'redirect' without a uri");
}
} elsif ($header_type eq 'header' ) {
my %props = $self->header_props();
#if we have any header props then use CGI to handle them
if( scalar(%props) ) {
require CGI;
my $cgi = CGI->new();
my $header = $cgi->header(%props);
$self->query->send_cgi_header($header) if($header);
} else {
# else use Apache send the header
$self->query->send_http_header('text/html');
}
} elsif( $header_type eq 'none' ) {
# don't do anything here either...
} else {
# croak() if we have an unknown header type
croak ("Invalid header_type '$header_type'");
}
# Don't return anything so headers aren't sent twice
return "";
}
1;
__END__
=pod
=head1 NAME
CGI::Application::Plugin::Apache - Allow CGI::Application to use Apache::* modules
without interference
=head1 SYNOPSIS
use base 'CGI::Application';
use CGI::Application::Plugin::Apache qw(:all);
# then later we join our hero in a run mode...
sub mode1 {
my $self = shift;
my $q = $self->query(); # $q is an Apache::Request obj not a CGI.pm obj
# do some stuff
# now we can bake a cookie using Apache::Cookie without interference
$cookie = Apache::Cookie->new(
$q,
-name => 'foo',
-value => 'bar',
-expires => '+2h',
);
$cookie->bake;
# now let's play with the content_type and other headers
$q->content_type('text/plain');
$q->header_out('MyHeader' => 'MyValue');
# do other stuff
return $content;
}
1;
=head1 DESCRIPTION
This plugin helps to try and fix some of the annoyances of using L<CGI::Application> in
a pure mod_perl environment. L<CGI::Application> assumes that you use L<CGI.pm|CGI>,
but I wanted
to avoid it's bloat and have access to the performance of the Apache::* modules so
along
came this plugin. At the current moment it only does two things:
=over
=item Use Apache::Request as the C<< $self->query >> object thus avoiding the creation
of the CGI.pm object.
=item Override the way L<CGI::Application> creates and prints it's HTTP headers. Since
it was using
L<CGI.pm|CGI>'s C<< header() >> and C<< redirect() >> method's we needed an
alternative. So now we
use the C<< Apache->send_http_header() >> method. This has a few additional benefits
other
than just not using L<CGI.pm|CGI>. It means that we can use other Apache::* modules
that might
also create outgoing headers (e.g. L<Apache::Cookie>) without L<CGI::Application>
clobbering
them.
=back
=head1 EXPORTED METHODS
This module uses L<Exporter> to provide methods to your application module. Most of
the time
you will never actually use these methods since they are used by L<CGI::Application>
itself,
but I figured you'd like to know what's going on.
No methods are exported by default. It is up to you to pick and choose, but please
choose
wisely. You can import all of the methods by using:
use CGI::Application::Plugin::Apache qw(:all);
It is recommended that you import all of them since some methods will require others..
but
the choice is yours. For instance, if you want to override any method then you may not
want
to import it from here.
=head2 handler()
This method gives your application the ability to run as a straight mod_perl handler.
It simply
creates an instance of you application and then runs it (using C<< $app->new() >> and
C<< $app->run() >>). It does not pass any arguments into either method. It then
returns an
C<< Apache::Constants::OK >> value. If you need anything more than this, please feel
free to
not import this method and write your own. You could do it like this:
package MyApp;
use base 'CGI::Application';
use CGI::Application::Plugin::Apache qw(:all !handler);
sub handler {
# do what every you want here
}
=head2 cgiapp_get_query()
This overrides CGI:App's method for retrieving the query object. This is the standard
way
of using something other than CGI.pm so it's no surprise that we use it here. It simply
creates and returns a new L<Apache::Request> object from C<< Apache->request >>.
=head2 _send_headers()
I didn't like the idea of exporting this private method (I'd rather think it was a
'protected'
not 'private) but right now it's the only way to have any say in how the HTTP headers
are created.
This method will only recognize the following values set by the C<<
$self->header_type() >>
method:
=over
=item * header
If you have previously called C<< header_props() >> or C<< header_add() >> in your
code then
it mean we have to use L<CGI.pm|CGI> to actually create the headers. If you haven't
then we
use Apache to do it. See L<"HTTP Headers"> for more details.
=item * none
The means we don't send any headers and it's up to the user to send them however they
want.
=item * redirect
This should function just the same as L<CGI::Application> normally does, except that
it will
try to use L<Apache> to send the headers and not L<CGI.pm|CGI>.
=back
=head1 HTTP Headers
=head2 Cookies
HTTP headers (and hence HTTP cookies) are now not created with C<< header_add() >> or
C<< header_props() >>.
Instead use L<Apache::Cookie> for cookies and anything you want for additional header
manipulation.
=head2 Redirects
You can still do the following to perform an HTTP redirect
$self->header_props( uri => $some_url);
$self->header_type('redirect');
return '';
But now we encourage you to do the following
$self->query->header_out(Location => $some_url);
$self->query->status(REDIRECT);
return '';
But it's really up to you.
=head1 CAVEATS
Upon using this module you completely leave behind the world of L<CGI.pm|CGI>. Don't
look back or
you might turn into a pillar of salt. You will have to look at and read the docs of
the Apache::*
modules. But don't worry, they are really easy to use and were designed to mimic the
interface
of L<CGI.pm|CGI>.
If you are trying to use this module but don't want to have to change your previous
code that
uses C<< header_props() >> or C<< header_add() >> then we try to help you out. We do
this by
actually requiring CGI and then passing those values along. We recommend that you
learn the
mod_perl way of baking cookies and setting outgoing header values. If you still want
to use
C<< header_props() >> or C<< header_add() >> remeber that it will cause a performance
hit.
Also it's important to note that you can't combine both methods. This means you can't
combine
calls of C<< header_props() >> or C<< header_add() >> with C<< header_out >> or C<<
status >>
within the same sequence of events.
=head1 AUTHOR
Michael Peters <[EMAIL PROTECTED]>
=head1 SEE ALSO
=over 8
=item * L<CGI::Application>
=item * L<Apache>
=item * L<Apache::Registry>
=item * L<Apache::Cookie>
=back
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
--------------------------------------------------------------------- Web Archive: http://www.mail-archive.com/[EMAIL PROTECTED]/ http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2 To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
