How to pass environment variable to an AutoLoaded mod_perl handler, to be used at module load time?

StackOverflow https://stackoverflow.com/questions/14778981

  •  07-03-2022
  •  | 
  •  

Question

I have a HTTP Request Handler for mod_perl which needs to read an environment variable, from %ENV, at module load time. The environment variable is passed from the Apache config into mod_perl using the PerlSetEnv directive.

This worked fine, until we changed the Apache configuration to AutoLoad the handler at startup time, for performance reasons. When the module is AutoLoaded like this, thePerlSetEnv does not take effect at module load time, and the variable we need is only available from %ENV at request time inside the handler method.

Is there a way to continue using AutoLoad, but still set an environment variable in the Apache config which is available in Perl's %ENV at module load time?

Minimal example:

Here's a stripped down test-case to illustrate the problem.

The Apache config without autoload enabled:

PerlSwitches -I/home/day/modperl
<Location /perl>
    SetHandler modperl
    PerlSetEnv TEST_PERLSETENV 'Does it work?'
    PerlResponseHandler ModPerl::Test
    Allow from all
</Location>

Contents of /home/day/modperl/ModPerl/Test.pm:

package ModPerl::Test;

use strict;
use warnings;

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const qw(OK);

my %ENV_AT_MODULE_LOAD = %ENV; # Take a copy

sub handler {
    my $r = shift;
    $r->content_type('text/plain');

    $r->print("ENV:\n");
    foreach my $key (sort keys %ENV) {
        $r->print("  $key: $ENV{$key}\n");
    }   

    $r->print("ENV_AT_MODULE_LOAD:\n");
    foreach my $key (sort keys %ENV_AT_MODULE_LOAD) {
        $r->print("  $key: $ENV_AT_MODULE_LOAD{$key}\n");
    }   

    return OK;
}   
1;

When localhost/perl is viewed in the browser, I see this:

ENV:
  MOD_PERL: mod_perl/2.0.5
  MOD_PERL_API_VERSION: 2
  PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  TEST_PERLSETENV: Does it work?
ENV_AT_MODULE_LOAD:
  MOD_PERL: mod_perl/2.0.5
  MOD_PERL_API_VERSION: 2
  PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  TEST_PERLSETENV: Does it work?

Hooray! TEST_PERLSETENV is available at module load time, as we want.

But when we change the Apache config to enable Autoload (by using + in the PerlResponseHandler like so):

    PerlResponseHandler +ModPerl::Test

I get the following output instead:

ENV:
  MOD_PERL: mod_perl/2.0.5
  MOD_PERL_API_VERSION: 2
  PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  TEST_PERLSETENV: Does it work?
ENV_AT_MODULE_LOAD:
  MOD_PERL: mod_perl/2.0.5
  MOD_PERL_API_VERSION: 2
  PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Boo! TEST_PERLSETENV is no longer available at module load time :( How can I get it back while keeping the AutoLoad behaviour?

Was it helpful?

Solution

Argh, 30 seconds after posting this question, I found the answer. Thank you rubber duck.

Move the PerlSetEnv to before the <Location> block which contains the PerlResponseHandler directive, and it works again!

i.e. like this:

PerlSwitches -I/home/dbarr/modperl
PerlSetEnv TEST_PERLSETENV 'Does it work?'
<Location /perl>
    SetHandler modperl
    PerlResponseHandler +ModPerl::Test
    Allow from all
</Location>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top