Problem with EXEC_ON_READ, custom block content

Problem with EXEC_ON_READ, custom block content

am 24.03.2008 15:44:43 von John Hallam

I'm trying to create a custom block directive, following the
documentation in the ModPerl2 book (or the on-line documentation). The
minimal code for the problem I am seeing is below. I have the following
block in apache2.conf for the new block and the module is
in the /root/apache2 tree as required.

---
PerlSwitches -wT -Mlib=/root/apache2
PerlLoadModule MyApache::StdVHost;




Order deny,allow
Deny from all


---

I see two behaviours: if EXEC_ON_READ is set, by removing the
string ', #' in the code below, the handler is never invoked -- at least
die "..." is not visibly executed; if EXEC_ON_READ is unset, the handler
is invoked but $cont is just the first line and not
the whole block. Neither is what I wanted :-((.

The problem seems to have been reported back in 2005, with similar
code, and an implication that it was to be fixed. So what am I doing
wrong?

Thanks in advance,

John Hallam

---
# PERL module for automating a standard virtual host configuration for Apache

package MyApache::StdVHost;

use strict;
use warnings FATAL => 'all';

use Apache2::Const -compile => qw(RSRC_CONF RAW_ARGS EXEC_ON_READ);

use Apache2::CmdParms ();
use Apache2::Module ();
use Apache2::Directive ();

use Apache2::ServerUtil ();

my @directives
= (
# Definition of a StdVHost container
#
# Note that EXEC_ON_READ is necessary, according to the
# mod_perl2 book, but in fact breaks things if included
# by stopping the handler from being called.

{
name => ' func => __PACKAGE__ . '::StdVHost',
errmsg => 'StdVHost minimal test package',
args_how => Apache2::Const::RAW_ARGS,
req_override => Apache2::Const::RSRC_CONF, #| Apache2::Const::EXEC_ON_READ,
},
);

Apache2::Module::add( __PACKAGE__, \@directives );

# Handler for the config directive.
#
# It is unclear how to get the content of the directive
# container: maybe it has not been read when this routine is called?
# With RAW_ARGS, the first line of the content is available as
# $parms->directive->as_string but how do you get the rest??

sub StdVHost {
my ($self,$parms,$arg) = @_;
my $cont = $parms->directive->as_string();

die "StdVHost arg='$arg' cont='$cont'";
}

1;

Re: Problem with EXEC_ON_READ, custom block content

am 20.04.2008 18:58:21 von Frederic Paillart

This is a multi-part message in MIME format.
--------------040701080306090006010108
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit

Hi John,

I've written such custom container few weeks ago,
and meet the same problems as you.

First, don't use the EXEC_ON_READ option.
Indeed, it doesn't work. Unfortunately, I don't know why.
But it doesn't care, you can perform your job without using it.

I've written a small perl function to solve the as_string issue.

# Unfortunately, directive->as_string doesn't expand
# the content of all embeded sub-containers.
# Because directive->as_string seems to be buggy
# We load the content of the custom container
# by recursing into the directive tree
sub loadContent {
my ($directive, $contentRef) = @_;

my @newContent;
for (my $currentDirective = $directive->first_child;
$currentDirective; $currentDirective = $currentDirective->next) {
if ($currentDirective->first_child) {
my ($containerName) = $currentDirective->directive =~
m/<\s*(.+)$/;

die "Container directive expected instead of " .
$currentDirective->directive unless ($containerName);

my $containerBegin = $currentDirective->directive . " " .
$currentDirective->args;
push(@newContent, $containerBegin);
loadContent($currentDirective, \@newContent);
my $containerEnd = "";
push(@newContent, $containerEnd);
} else {
my $line = $currentDirective->directive . " " .
$currentDirective->args;
push(@newContent, $line);
}
}

push(@$contentRef, @newContent);
}

Finally, you can write your custom container using this function :

use strict;
use warnings FATAL => 'all';
use Apache2::Const -compile => qw(NO_ARGS OR_ALL RAW_ARGS);

use Apache2::CmdParms ();
use Apache2::Module ();
use Apache2::Directive ();
use Apache2::ServerUtil ();

my @directives = (
{
name => ' func => __PACKAGE__ . '::StdVHost',
req_override => Apache2::Const::OR_ALL,
args_how => Apache2::Const::RAW_ARGS,
errmsg => 'Std vhosts container',
},
{
name => '',
func => __PACKAGE__ . "::StdVHost_END",
errmsg => 'end of StdVHost without beginning?',
args_how => Apache2::Const::NO_ARGS,
req_override => Apache2::Const::OR_ALL,
},
);
Apache2::Module::add(__PACKAGE__, \@directives);

sub StdVHost {
my ($self, $parms, $arg) = @_;

# Load the container configuration content
my $directive = $parms->directive;
my @content;
loadContent($directive, \@content);

# ... Do your custom job
# For example dynamically add apache configuration directives read
inside the custom container :
Apache2::ServerUtil->server->add_config(\@content);
}


sub StdVHost_END {
die " outside a container\n";
}


Hope this example can help you.

Best regards

Fred


Le 23.12.-28158 20:59, John Hallam a écrit :
>
> I'm trying to create a custom block directive, following the
> documentation in the ModPerl2 book (or the on-line documentation).
> The minimal code for the problem I am seeing is below. I have the
> following block in apache2.conf for the new block and
> the module is in the /root/apache2 tree as required.
>
> ---
> PerlSwitches -wT -Mlib=/root/apache2
> PerlLoadModule MyApache::StdVHost;
>
>
>
>
> Order deny,allow
> Deny from all
>

>

> ---
>
> I see two behaviours: if EXEC_ON_READ is set, by removing the
> string ', #' in the code below, the handler is never invoked -- at
> least die "..." is not visibly executed; if EXEC_ON_READ is unset,
> the handler is invoked but $cont is just the first line > /var/www> and not the whole block. Neither is what I wanted :-((.
>
> The problem seems to have been reported back in 2005, with similar
> code, and an implication that it was to be fixed. So what am I doing
> wrong?
>
> Thanks in advance,
>
> John Hallam
>
> ---
> # PERL module for automating a standard virtual host configuration for
> Apache
>
> package MyApache::StdVHost;
>
> use strict;
> use warnings FATAL => 'all';
>
> use Apache2::Const -compile => qw(RSRC_CONF RAW_ARGS EXEC_ON_READ);
>
> use Apache2::CmdParms ();
> use Apache2::Module ();
> use Apache2::Directive ();
>
> use Apache2::ServerUtil ();
>
> my @directives
> = (
> # Definition of a StdVHost container
> #
> # Note that EXEC_ON_READ is necessary, according to the
> # mod_perl2 book, but in fact breaks things if included
> # by stopping the handler from being called.
>
> {
> name => ' > func => __PACKAGE__ . '::StdVHost',
> errmsg => 'StdVHost minimal test package',
> args_how => Apache2::Const::RAW_ARGS,
> req_override => Apache2::Const::RSRC_CONF, #|
> Apache2::Const::EXEC_ON_READ,
> },
> );
>
> Apache2::Module::add( __PACKAGE__, \@directives );
>
> # Handler for the config directive.
> #
> # It is unclear how to get the content of the directive
> # container: maybe it has not been read when this routine is called?
> # With RAW_ARGS, the first line of the content is available as
> # $parms->directive->as_string but how do you get the rest??
>
> sub StdVHost {
> my ($self,$parms,$arg) = @_;
> my $cont = $parms->directive->as_string();
>
> die "StdVHost arg='$arg' cont='$cont'";
> }
>
> 1;
>

--------------040701080306090006010108
Content-Type: text/x-vcard; charset=utf-8;
name="Frederic_PAILLART.vcf"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="Frederic_PAILLART.vcf"

begin:vcard
fn:Frederic Paillart
n:Paillart;Frederic
org:gemalto;WSDS
adr:ZI Athelia IV;;La Vigie;La Ciotat;;13705;France
email;internet:frederic.paillart@gemalto.com
title:Development Engineer
tel;work:04 42 36 43 38
tel;fax:04 42 36 32 00
x-mozilla-html:TRUE
url:http://www.gemalto.com
version:2.1
end:vcard


--------------040701080306090006010108--