You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Justin Luster <ju...@sawtoothsoftware.com> on 2005/08/16 18:57:09 UTC

Mod_Perl 2.0 Header question

Hi, I was hoping to get a bit of help on how to send the proper HTTP
headers using Mod_Perl.  We create Perl scripts and then ship them out
to our clients for them to run on their servers.  The script should work
on regular CGI and Mod_Perl if they have it.  Things have worked fine so
far.  But now Mod_Perl 2.0 is starting to be installed on servers
throughout the world and I need to modify my script so that it will work
with it also.  I only use Mod_Perl to speed up regular CGI using
"registry".

 

I have a main.pl file that "requires" a helper.pl file.  In the
helper.pl I have the code that produces the HTTP header.  It is in the
helper.pl because both main.pl and main2.pl need it.

 

My current code looks something like this:

 

sub PrintHeader 

{

            my $strOut = "";

            my $blnModPerl = 0;

            my $intModPerlVersion = 0;

            my $strDefaultContentType = "";

 

            $strDefaultContentType .= "Content-type: text/html\r\n\r\n";

 

            if (exists($ENV{'MOD_PERL'}) && defined($ENV{'MOD_PERL'})) 

            {

                        $blnModPerl = 1;

 

                        $intModPerlVersion = $ENV{'MOD_PERL'};

 

                        # Change mod_perl/1.XX to 1.X

                        $intModPerlVersion =~
s/mod_perl\/(\d\.\d)(.*?)$/$1/i;

            }

 

            if ($ENV{'PERL_SEND_HEADER'} || ($blnModPerl == 0)) 

            {

                        $strOut = $strDefaultContentType;

            }

            else

            {

                        my $r = Apache->request;

                        

                        $r->content_type('text/html');

 

                        #Only call send_http_header for mod_perl
versions prior to (1.9) in the 1.26 series 

                        #Remember to update this in admin.pl too

                        if ($intModPerlVersion < 1.9) 

                        {

                                    $r->send_http_header;

                        }

            }

 

            $authlib::blnPrintedHeaders = 1;

 

            return $strOut;

}

 

I find that this breaks under some versions of Mod_Perl 2.0.  I'm
working with two older versions: 1.99_07-dev and 1.99_12 both on Linux
machines.

 

My confusion is how to send the proper 2.0 header.  In my in-house
version Apache->request; does not seem to work.  The 2.0 documentation
says use Apache2::RequestUtil but that does not work either.  My clients
version however works with Apache->request and I'm confused as to why.

 

The bottom line is I want to have a function like the one above that
will work for CGI, mod_perl 1.0 and mod_perl 2.0.  I'd like this
function to be in a common library (helper.pl) so that main1.pl and
main2.pl can use it.

 

>From reading the documentation I realize that there is a function called
"handler()" and that you can get a hold of $r somehow.  So I tried it
out and came up with something like this:

 

use strict;

 

my $ModPerlObj = @_[0];

 

main::main();

 

package main;

 

sub main

{

            authlib::Initialize($ModPerlObj);

}

 

This seems to work because as I understand it Mod_Perl wraps up the
contents of main.pl and places it inside a function called "handler( )".
"handler( )" then receives an Apache Object.  So I'm getting it using
@_[0] and then passing it into my function.

 

Is this bad practice?  Any "cons" to doing it this way?

 

I just want a simple way to create the header.

 

Please help.

 

Thanks,

 

Justin

 


RE: Mod_Perl 2.0 Header question

Posted by Justin Luster <ju...@sawtoothsoftware.com>.
Perrin responded to my question below.  His response works with what I'm
trying to do.  Let me know if you think this is a bad idea.

On Tue, 2005-08-16 at 09:20 -0700, Justin Luster wrote:
> The way it relates is that in the previous code I was doing this:
> 
>   my $r = Apache->request;
> 
>   $r->content_type('text/html');
> 
> It seems that in Mod_Perl 2.0 this does not work.

It has changed to this:
Apache2::RequestUtil->request()

And you need to set this in your conf:
PerlOptions +GlobalRequest

Read the porting guide:
http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache_E_gt_r
equest_

> From
> the documentation that I read it seems that Mod_Perl wraps up my 
> main.pl code into a "handler()" function.  The documentation then 
> describes that it passes the ApacheObj as the 1st parameter to this 
> function.

That's correct, you can get it that way.

> So by
> doing this:
> 
> my $ModPerlObj = @_[0];
> 
> I'm able to get that ApacheObj and pass it to my code.  I don't think 
> that I need it to be different for each request.

No, you really do.  When you create a closure, it keeps the first
request that comes in and you will never be setting the content-type on
any request after that.  I expect it will fail and possibly cause memory
problems.  All you need to do to fix your code is to pass $r instead of
making a closure:

use strict;
use warnings;

my $r = shift;
main::start($r);

package main;

sub start {
    my $r = shift;
    authlib::Initialize($r);
}


I'm not sure it's worth having the separate sub at all though, if that's
all that's in it.

> We ship our code out to clients throughout the world.  Because of this

> our code could be run on any type of Mod_Perl system.  So it would be 
> nice to find a method that would work with anything out there.  It is 
> frustrating that something as simple as this could not stay consistent

> across versions.

You can't really expect your code to work on beta pre-release versions.
People need to keep up to some degree if they want to use unstable code.
The 2.0 release is stable, and the 1.x series is stable.  Pre-release
versions of 2.0 are totally unsupported.


> We generally do not rely on outside Perl libraries.  We try to keep 
> all of the code that our clients need wrapped up in our Perl files.  
> This way we are not relying on the end computer as much.

We do this too, by packaging all of the CPAN modules we use in a bundle
that we compile and access locally, not from site_perl.

> Sorry, I'm not the "Musician's Friend" but I'm still a nice guy :)

I remember your winning photo from last year.  This year's was not as
good.

- Perrin

-----Original Message-----
From: Philip M. Gollucci [mailto:pgollucci@p6m7g8.com] 
Sent: Tuesday, August 16, 2005 10:36 AM
To: Justin Luster
Cc: modperl@perl.apache.org
Subject: Re: Mod_Perl 2.0 Header question

 >I find that this breaks under some versions of Mod_Perl 2.0.  I'm 
 >working with two older versions: 1.99_07-dev and 1.99_12 both on Linux

 >machines.
You should really try to use at least RC 5+

> My confusion is how to send the proper 2.0 header.  In my in-house 
> version Apache->request; does not seem to work.  The 2.0 documentation

> says use Apache2::RequestUtil but that does not work either.  My
clients 
> version however works with Apache->request and I'm confused as to why.
Apache2::RequestUtil doesn't exist in the versions you mentioned.  Its 
still called Apache::RequestUtil.
http://perl.apache.org/docs/2.0/rename.html

To answer your question though, I believe you could do something like 
this, *untested*

unless ($ENV{GATEWAY_INTERFACE} =~ /Perl/) {
   ## CGI script or commandline

   if ($ENV{GATEWAY_INTERFACE} =~ /CGI/) {
     ## CGI
   }
   else {
     ## Commandline
   }
}
elsif ($ENV{MOD_PERL_API_VERSION} == 2) {
   ## mod_perl 2 RC 5 +
}
elsif (eval { require mod_perl } && $mod_perl::VERSION > 1.99) {
   ## mod_perl 1.9900 -> 1.99022 which is RC4
}
elsif ( $mod_perl::VERSION < 1.99) {
   ## mod_perl 1.x
}
else {
   ## fatal error .. I don't think this will get hit
}

Also, to send content headers in at least mp2, you should be using

i.e.
$r->content_header('text/html');


END
------------------------------------------------------------
     What doesn't kill us can only make us stronger.
                 Nothing is impossible.
				
Philip M. Gollucci (pgollucci@p6m7g8.com) 301.254.5198
Consultant / http://p6m7g8.net/Resume/
Senior Developer / Liquidity Services, Inc.
   http://www.liquidityservicesinc.com
        http://www.liquidation.com
        http://www.uksurplus.com
        http://www.govliquidation.com
        http://www.gowholesale.com



Re: Mod_Perl 2.0 Header question

Posted by "Philip M. Gollucci" <pg...@p6m7g8.com>.
 >I find that this breaks under some versions of Mod_Perl 2.0.  I’m 
 >working with two older versions: 1.99_07-dev and 1.99_12 both on Linux 
 >machines.
You should really try to use at least RC 5+

> My confusion is how to send the proper 2.0 header.  In my in-house 
> version Apache->request; does not seem to work.  The 2.0 documentation 
> says use Apache2::RequestUtil but that does not work either.  My clients 
> version however works with Apache->request and I’m confused as to why.
Apache2::RequestUtil doesn't exist in the versions you mentioned.  Its 
still called Apache::RequestUtil.
http://perl.apache.org/docs/2.0/rename.html

To answer your question though, I believe you could do something like 
this, *untested*

unless ($ENV{GATEWAY_INTERFACE} =~ /Perl/) {
   ## CGI script or commandline

   if ($ENV{GATEWAY_INTERFACE} =~ /CGI/) {
     ## CGI
   }
   else {
     ## Commandline
   }
}
elsif ($ENV{MOD_PERL_API_VERSION} == 2) {
   ## mod_perl 2 RC 5 +
}
elsif (eval { require mod_perl } && $mod_perl::VERSION > 1.99) {
   ## mod_perl 1.9900 -> 1.99022 which is RC4
}
elsif ( $mod_perl::VERSION < 1.99) {
   ## mod_perl 1.x
}
else {
   ## fatal error .. I don't think this will get hit
}

Also, to send content headers in at least mp2, you should be using

i.e.
$r->content_header('text/html');


END
------------------------------------------------------------
     What doesn't kill us can only make us stronger.
                 Nothing is impossible.
				
Philip M. Gollucci (pgollucci@p6m7g8.com) 301.254.5198
Consultant / http://p6m7g8.net/Resume/
Senior Developer / Liquidity Services, Inc.
   http://www.liquidityservicesinc.com
        http://www.liquidation.com
        http://www.uksurplus.com
        http://www.govliquidation.com
        http://www.gowholesale.com