Implementing a custom config directive (AP_INIT_TAKE1) in mod_perl 2
am 22.10.2010 17:19:15 von Alexander Farber
Hello,
I have a simple protocol handler which writes a string to client
socket (source code below).
I would like to make that string configurable through httpd.conf, so
that I could say there:
Listen 843
MyPolicyString "blah"
PerlModule SocketPolicy
PerlProcessConnectionHandler SocketPolicy
I keep reading http://perl.apache.org/docs/2.0/user/ and other docs,
but just can't find how to do it. Do you use PerlPostConfigHandler for
that and how would I get that string in my
PerlProcessConnectionHandler?
I've noticed, that I could use a Apache2::Directive or a
$r->dir_config("MyPerlVar") but those seem to be slower and are
mod_perl-ish. I would like to use the mod_perl method corresponding to
the command_rec structure in C, where you would use an AP_INIT_TAKE1
(I guess... I'm not an expert here).
Thanks
Alex
package SocketPolicy;
use strict;
use warnings FATAL => 'all';
use APR::Const(-compile => 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile => qw(OK DECLINED));
use constant POLICY =>
qq{
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
\0};
sub handler {
my $conn = shift;
my $socket = $conn->client_socket();
my $offset = 0;
# set the socket to the blocking mode
$socket->opt_set(APR::Const::SO_NONBLOCK => 0);
# XXX use the policy string coming from httpd.conf XXX
do {
my $nbytes = $socket->send(substr(POLICY, $offset),
length(POLICY) - $offset);
# client connection closed or interrupted
return Apache2::Const::DECLINED unless $nbytes;
$offset += $nbytes;
} while ($offset < length(POLICY));
my $slog = $conn->base_server()->log();
$slog->warn('served socket policy to: ', $conn->remote_ip());
return Apache2::Const::OK;
}
1;
Re: Implementing a custom config directive (AP_INIT_TAKE1) in mod_perl 2
am 22.10.2010 19:03:32 von torsten.foertsch
On Friday, October 22, 2010 17:19:15 Alexander Farber wrote:
> Hello,
>=20
> I have a simple protocol handler which writes a string to client
> socket (source code below).
>=20
> I would like to make that string configurable through httpd.conf, so
> that I could say there:
>=20
> Listen 843
>
> MyPolicyString "blah"
> PerlModule SocketPolicy
> PerlProcessConnectionHandler SocketPolicy
>
>=20
> I keep reading http://perl.apache.org/docs/2.0/user/ and other docs,
> but just can't find how to do it. Do you use PerlPostConfigHandler for
> that and how would I get that string in my
> PerlProcessConnectionHandler?
>=20
> I've noticed, that I could use a Apache2::Directive or a
> $r->dir_config("MyPerlVar") but those seem to be slower and are
> mod_perl-ish. I would like to use the mod_perl method corresponding to
> the command_rec structure in C, where you would use an AP_INIT_TAKE1
> (I guess... I'm not an expert here).
use Apache2::CmdParms ();
use Apache2::Directive ();
use Apache2::Module ();
my @directives=3D
(
{
name =3D> 'SocketPolicyString',
req_override =3D> Apache2::Const::RSRC_CONF,
args_how =3D> Apache2::Const::TAKE1,
errmsg =3D> '...',
},
...
);
Apache2::Module::add(__PACKAGE__, \@directives);
sub SocketPolicyString {
my(undef, $parms, $arg)=3D@_;
my $cf=3DApache2::Module::get_config(__PACKAGE__, $parms->server);
$cf->{policystring}=3D$arg;
}
# merge merges the configurations of the vhost and the base server to build
# the final config for the vhost. that means here a vhost inherits from the
# base server.
sub SERVER_MERGE {
my ($base, $add)=3D@_;
my %merged;
if( exists $add->{policystring} ) {
$merged{policystring}=3D$add->{policystring};
} else {
$merged{policystring}=3D$base->{policystring};
}
return bless \%merged, ref($base);
}
# This is called only if there is at least one directive for the module in =
the
# httpd.conf for the server
sub SERVER_CREATE {
my ($class, $parms)=3D@_;
return bless {
policystring=3D>'defaultpolicy',
} =3D> $class;
}
Put something like that outside any function in your module.
In the httpd.conf you need to use PerlLoadModule instead of PerlModule to l=
oad=20
the module. After that you should be able to use
SocketPolicyString "hugo"
That is a short outline compiled from my memory. I may have missed somethin=
g=20
here very well.
Then at runtime (in your handler):
$cf=3DApache2::Module::get_config( __PACKAGE__, $conn->base_server );
There is more documentation on this on the site. Search for SERVER_MERGE or=
=20
so.
It is also possible to create container directives which is more convenient=
=20
for the user if the policy string may become longer. The user can then put =
it=20
as
blah blah
The corresponding @directives element would look like:
{
name =3D> '
func =3D> __PACKAGE__.'::SocketPolicyContainer',
req_override =3D> Apache2::Const::RSRC_CONF,
args_how =3D> Apache2::Const::RAW_ARGS,
errmsg =3D> <<'EOF',
...
EOF
},
and you'd have to implement a SocketPolicyContainer function and the=20
corresponding stuff in SERVER_CREATE/_MERGE as well.
sub SocketPolicyContainer {
my(undef, $parms, $rest)=3D@_;
$cf=3DApache2::Module::get_config(__PACKAGE__, $parms->server);
# $rest contains the stuff after "
">"
# the stuff between the opening and closing "" lines =
is
# read as $parms->directive->as_string
...
}
You can have both the simple string SocketPolicyString directive and the=20
container directive at once.
Torsten Förtsch
=2D-=20
Need professional modperl support? Hire me! (http://foertsch.name)
Like fantasy? http://kabatinte.net