stas 2002/12/09 08:47:07
Modified: src/docs/2.0/user config.cfg
Added: src/docs/2.0/user/config custom.pod
Log:
a new doc: Apache Server Configuration Customization in Perl
Revision Changes Path
1.1 modperl-docs/src/docs/2.0/user/config/custom.pod
Index: custom.pod
===================================================================
=head1 NAME
Apache Server Configuration Customization in Perl
=head1 Description
This chapter explains how to create custom Apache configuration
directives in Perl.
WARNING: This doc is under construction
=head1 Incentives
mod_perl provides several ways to pass custom configuration
information to the modules.
The simplest way to pass custom information from the configuration
file to the Perl module is to use the
C<L<PerlSetVar|docs::2.0::user::config::config/C_PerlSetVar_>> and
C<L<PerlAddVar|docs::2.0::user::config::config/C_PerlAddVar_>>
directives. For example:
PerlSetVar Secret "Matrix is us"
and in the mod_perl code this value can be retrieved as:
my $secret = $r->dir_config("Secret");
Another alternative is to add custom configuration directives. There
are several reasons for choosing this approach:
=over
=item *
When the expected value is not a simple argument, but must be supplied
using a certain syntax, Apache can verify at startup time that this
syntax is valid and abort the server start up if the syntax is
invalid.
=item *
Custom configuration directives are faster because their values are
parsed at the startup time, whereas C<PerlSetVar> and C<PerlAddVar>
values are parsed at the request time.
=item *
It's possible that some other modules have accidentally chosen to use
the same key names but for absolutely different needs. So the two now
can't be used together. Of course this collision can be avoided if a
unique to your module prefix is used in the key names. For example:
PerlSetVar ApacheFooSecret "Matrix is us"
=back
Finally, modules can be configured in pure Perl using
C<L<E<lt>PerlE<gt>
Sections|docs::2.0::user::config::config/C_E_lt_PerlE_gt___Sections>>
or L<a startup
file|docs::2.0::user::config::config/Startup_File>, by simply modifying
the global variables in the module's package. This approach could be
undesirable because it requires a use of globals, which we all try to
reduce. A bigger problem with this approach is that you can't have
different settings for different sections of the site (since there is
only one version of a global variable), something that the previous
two approaches easily achieve.
=head1 Creating and Using Custom Configuration Directives
In mod_perl 2.0, adding new configuration directives is a piece of
cake, because it requires no XS code and I<Makefile.PL>, needed in
case of mod_perl 1.0. In mod_perl 2.0, custom directives are
implemented in pure Perl.
Here is a very basic module that declares two new configuration
directives: C<MyParameter>, which accepts one or more arguments, and
C<MyOtherParameter> which accepts a single argument.
#file:MyApache/MyParameters.pm
#-----------------------------
package MyApache::MyParameters;
use strict;
use warnings FATAL => 'all';
use Apache::Test;
use Apache::TestUtil;
use Apache::Const -compile => qw(OR_ALL ITERATE);
use Apache::CmdParms ();
use Apache::Module ();
our @APACHE_MODULE_COMMANDS = (
{
name => 'MyParameter',
func => __PACKAGE__ . '::MyParameter',
req_override => Apache::OR_ALL,
args_how => Apache::ITERATE,
errmsg => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
},
{
name => 'MyOtherParameter',
},
);
sub MyParameter {
my($self, $parms, @args) = @_;
$self->{MyParameter} = [EMAIL PROTECTED];
}
1;
And here is how to use it in I<httpd.conf>:
# first load the module so Apache will recognize the new directives
PerlLoadModule MyApache::MyParameters
MyParameter one two three
MyOtherParameter Foo
<Location /perl>
MyParameter eleven twenty
MyOtherParameter Bar
</Location>
The following sections discuss this and more advanced modules in
detail.
A minimal configuration module is comprised of two groups of elements:
=over
=item * A global array C<@APACHE_MODULE_COMMANDS> for declaring the
new directives and their behavior.
=item * A subroutine per each new directive, which is called when the
directive is seen
=back
=head2 C<@APACHE_MODULE_COMMANDS>
C<@APACHE_MODULE_COMMANDS> is a global array of hash references. Each
hash represents a separate new configuration directive. In our example
we had:
our @APACHE_MODULE_COMMANDS = (
{
name => 'MyParameter',
func => __PACKAGE__ . '::MyParameter',
req_override => Apache::OR_ALL,
args_how => Apache::ITERATE,
errmsg => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
},
{
name => 'MyOtherParameter',
},
);
This structure declares two new directives: C<MyParameter> and
C<MyOtherParameter>. You have to declare at least the name of the new
directive, which is how we have declared the C<MyOtherParameter>
directive. mod_perl will fill in the rest of the configuration using
the defaults described next.
These are the attributes that can be used to define the directives
behavior:
=over
=item * name
This is the only required attribute. And it declares the name of the
new directive as it'll be used in I<httpd.conf>.
=item * func
The I<func> attribute expects a reference to a function or a function
name. This function is called by httpd every time it encounters the
directive that is described by this entry while parsing the
configuration file. Therefore it's invoked once for every instance of
the directive at the server startup, and once per request per instance
in the I<.htaccess> file.
This function accepts two or more arguments, L<depending on the
I<args_how> attribute's value|/Directive_Syntax_Definition_Constants>.
This attribute is optional. If not supplied, mod_perl will try to use
a function in the current package whose name is the same as of the
directive in question. In our example with C<MyOtherParameter>,
mod_perl will use:
__PACKAGE__ . '::MyOtherParameter'
as a name of a subroutine and it anticipates that it exists in that
package.
=item * req_override
The I<> attribute defines the valid scope in which this directive can
appear. There are L<several
constants|/Directive_Scope_Definition_Constants> which map onto the
corresponding Apache macros. These constants should be imported from
the C<Apache::Const> package.
For example, to use the C<OR_ALL> constant, which allows directives to
be defined anywhere, first, it needs to be imported:
use Apache::Const -compile => qw(OR_ALL);
and then assigned to the I<req_override> attribute:
req_override => Apache::OR_ALL,
It's possible to combine several options using the unary
operators. For example, the following setting:
req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF
will allow the directive to appear anywhere in I<httpd.conf>, but
forbid it from ever being used in I<.htaccess> files:
This attribute is optional. If not supplied, the default value of
C<Apache::OR_ALL> is used.
=item * args_how
Directives can receive zero, one or many arguments. In order to help
Apache validate that the number of arguments is valid, the I<args_how>
attribute should be set to the desired value. Similar to the
I<req_override> attribute, the C<Apache::Const> package provides
special constants which map to the corresponding Apache macros. There
are L<several constants|/Directive_Syntax_Definition_Constants> to
choose from.
In our example, the directive C<MyParameter> accepts one or more
arguments, therefore we have the C<Apache::ITERATE> constant:
args_how => Apache::ITERATE,
This attribute is optional. If not supplied, the default value of
C<Apache::TAKE1> is used.
META: the default may change to use a constant corresponding to the
I<func> prototype.
=item * errmsg
The I<errmsg> attribute provides a short but succinct usage statement
that summarizes the arguments that the directive takes. It's used by
Apache to generate a descriptive error message, when the directive is
configured with a wrong number of arguments.
In our example, the directive C<MyParameter> accepts one or more
arguments, therefore we have chosen the following usage string:
errmsg => 'MyParameter Entry1 [Entry2 ... [EntryN]]',
This attribute is optional. If not supplied, the default value of will
be a string based on the directive's I<name> and I<args_how>
attributes.
=back
=head2 Directive Scope Definition Constants
The I<req_override> attribute specifies the configuration scope in
which it's valid to use a given configuration directive. This
attribute's value can be any of or a combination of the following
constants:
(these constants are declared in I<httpd-2.0/include/http_config.h>.)
=head3 C<Apache::OR_NONE>
The directive cannot be overriden by any of the C<AllowOverride>
options.
=head3 C<Apache::OR_LIMIT>
The directive can appear within directory sections, but not outside
them. It is also allowed within I<.htaccess> files, provided that
C<AllowOverride Limit> is set for the current directory.
=head3 C<Apache::OR_OPTIONS>
The directive can appear anywhere within I<httpd.conf>, as well as
within I<.htaccess> files provided that C<AllowOverride Options> is
set for the current directory.
=head3 C<Apache::OR_FILEINFO>
The directive can appear anywhere within I<httpd.conf>, as well as
within I<.htaccess> files provided that C<AllowOverride FileInfo> is
set for the current directory.
=head3 C<Apache::OR_AUTHCFG>
The directive can appear within directory sections, but not outside
them. It is also allowed within I<.htaccess> files, provided that
C<AllowOverride AuthConfig> is set for the current directory.
=head3 C<Apache::OR_INDEXES>
The directive can appear anywhere within I<httpd.conf>, as well as
within I<.htaccess> files provided that C<AllowOverride Indexes> is
set for the current directory.
=head3 C<Apache::OR_UNSET>
META: details? "unset a directive (in Allow)"
=head3 C<Apache::ACCESS_CONF>
The directive can appear within directory sections. The directive is
not allowed in I<.htaccess> files.
=head3 C<Apache::RSRC_CONF>
The directive can appear in I<httpd.conf> outside a directory section
(C<E<lt>DirectoryE<gt>>, C<E<lt>LocationE<gt>> or C<E<lt>FilesE<gt>>;
also C<E<lt>FilesMatchE<gt>> and kin). The directive is not allowed
in I<.htaccess> files.
=head3 C<Apache::OR_EXEC_ON_READ>
Force directive to execute a command which would modify the
configuration (like including another file, or C<IFModule>).
META: details???
=head3 C<Apache::OR_ALL>
The directive can appear anywhere. It is not limited in any way.
=head2 Directive Callback Subroutine
Depending on the value of the I<args_how> attribute the callback
subroutine, specified with the I<func> attribute, will be called with
two or more arguments. The first two arguments are always C<$self> and
C<$parms>. A typical callback function which expects a single value
(C<Apache::TAKE1>) might look like the following:
sub MyParam {
my($self, $parms, $arg) = @_;
$self->{MyParam} = $arg;
}
In this function we store the passed single value in the configuration
object, using the directive's name (assuming that it was C<MyParam>)
as the key.
Let's look at the subroutine arguments in detail:
=over
=item 1
C<$self> is the current container's configuration object.
This configuration object is a reference to a hash, in which you can
store arbitrary key/value pairs. When the directive callback function
is invoked it may already include several key/value pairs inserted by
other directive callbacks or during the
C<L<SERVER_CREATE|/C_SERVER_CREATE_>> and
C<L<DIR_CREATE|/C_DIR_CREATE_>> functions, which will be explained
later.
Usually the callback function stores the passed argument(s), which
later will be read by C<L<SERVER_MERGE|/C_SERVER_MERGE_>> and
C<L<DIR_MERGE|/C_DIR_MERGE_>>, which will be explained later, and of
course at request time.
The convention is use the name of the directive as the hash key, where
the received values are stored. The value can be a simple scalar, or a
reference to a more complex structure. So for example you can store a
reference to an array, if there is more than one value to store.
This object can be later retrieved at request time via:
my $dir_cfg = $self->get_config($s, $r->per_dir_config);
You can retrieve the server configuration object via:
my $srv_cfg = $self->get_config($s);
if invoked inside the virtual host, the virtual host's configuration
object will be returned.
=item 2
C<$parms> is an I<Apache::CmdParms> object from which you can retrieve
various other information about the configuration. For example to
retrieve the server object:
my $s = $parms->server;
See
C<L<Apache::CmdParms|docs::2.0::api::mod_perl-2.0::Apache::CmdParms>>
for more information.
=item 3
The rest of the arguments whose number depends on the I<args_how>'s
value are covered in L<the next
section|/Directive_Syntax_Definition_Constants>.
=back
=head2 Directive Syntax Definition Constants
The following values of the I<args_how> attribute define how many
arguments and what kind of arguments directives can accept. These
values are constants that can be imported from the C<Apache::Const>
package. For example:
use Apache::Const -compile => qw(TAKE1 TAKE23);
=head3 C<Apache::NO_ARGS>
The directive takes no arguments. The callback will be invoked once
each time the directive is encountered. For example:
sub MyParameter {
my($self, $parms) = @_;
$self->{MyParameter}++;
}
=head3 C<Apache::TAKE1>
The directive takes a single argument. The callback will be invoked
once each time the directive is encountered, and its argument will be
passed as the third argument. For example:
sub MyParameter {
my($self, $parms, $arg) = @_;
$self->{MyParameter} = $arg;
}
=head3 C<Apache::TAKE2>
The directive takes two arguments. They are passed to the callback as
the third and fourth arguments. For example:
sub MyParameter {
my($self, $parms, $arg1, $arg2) = @_;
$self->{MyParameter} = {$arg1 => $arg2};
}
=head3 C<Apache::TAKE3>
This is like C<Apache::TAKE1> and C<Apache::TAKE2>, but the directive
takes three mandatory arguments. For example:
sub MyParameter {
my($self, $parms, @args) = @_;
$self->{MyParameter} = [EMAIL PROTECTED];
}
=head3 C<Apache::TAKE12>
This directive takes one mandatory argument, and a second optional
one. This can be used when the second argument has a default value
that the user may want to override. For example:
sub MyParameter {
my($self, $parms, $arg1, $arg2) = @_;
$self->{MyParameter} = {$arg1 => $arg2||'default'};
}
=head3 C<Apache::TAKE23>
C<Apache::TAKE23> is just like C<Apache::TAKE12>, except now there are
two mandatory arguments and an optional third one.
=head3 C<Apache::TAKE123>
In the C<Apache::TAKE123> variant, the first argument is mandatory and
the other two are optional. This is useful for providing defaults for
two arguments.
=head3 C<Apache::ITERATE>
C<Apache::ITERATE> is used when a directive can take an unlimited
number of arguments. The callback is invoked repeatedly with a single
argument, once for each argument in the list. It's done this way for
interoperability with the C API, which doesn't have the flexible
argument passing that Perl provides. For example:
sub MyParameter {
my($self, $parms, $args) = @_;
push @{ $self->{MyParameter} }, $arg;
}
=head3 C<Apache::ITERATE2>
C<Apache::ITERATE2> is used for directives that take a mandatory first
argument followed by a list of arguments to be applied to the first.
A familiar example is the C<AddType> directive, in which a series of
file extensions are applied to a single MIME type:
AddType image/jpeg JPG JPEG JFIF jfif
Apache will invoke your callback once for each item in the list. Each
time Apache runs your callback, it passes the routine the constant
first argument (I<"image/jpeg"> in the example above), and the current
item in the list (I<"JPG"> the first time around, I<"JPEG"> the second
time, and so on). In the example above, the configuration processing
routine will be run a total of four times.
For example:
sub MyParameter {
my($self, $parms, $key, $val) = @_;
push @{ $self->{MyParameter}{$key} }, $val;
}
=head3 C<Apache::RAW_ARGS>
An I<args_how> of C<Apache::RAW_ARGS> instructs Apache to turn off
parsing altogether. Instead it simply passes your callback function
the line of text following the directive. Leading and trailing
whitespace is stripped from the text, but it is not otherwise
processed. Your callback can then do whatever processing it wishes to
perform.
This callback receives three arguments (similar to C<Apache::TAKE1>),
the third of which is a string-valued scalar containing the text
following the directive.
sub MyParameter {
my($self, $parms, $val) = @_;
# process $val
}
If this mode is used to implement a custom "container" directive, the
attribute I<req_override> needs to OR C<Apache::EXEC_ON_READ>. e.g.:
req_override => Apache::OR_ALL | Apache::EXEC_ON_READ,
META: complete the details, which are new to 2.0.
There is one other trick to making configuration containers work. In
order to be recogized as a valid directive, the I<name> attribute must
contain the leading C<E<lt>>. This token will be stripped by the code
that handes the custom directive callbacks to Apache. For example:
name => '<MyContainer',
One other trick that is not required, but can provide some more user
friendliness is to provide a handler for the container end token. In
our example, the Apache configuration gears will never see the
C<E<lt>/MyContainerE<gt>> token, as our C<Apache::RAW_ARGS> handler
will read in that line and stop reading when it is seen. However in
order to catch cases in which the C<E<lt>/MyContainerE<gt>> text
appears without a preceding C<E<lt>MyContainerE<gt>> opening section,
we need to turn the end token into a directive that simply reports an
error and exits. For example:
{
name => '</MyContainer>',
func => __PACKAGE__ . "::MyContainer_END",
errmsg => 'end of MyContainer without beginning?',
args_how => Apache::NO_ARGS,
req_override => Apache::OR_ALL,
},
...
my $EndToken = "</MyContainer>";
sub MyContainer_END {
die "$EndToken outside a <MyContainer> container\n";
}
Now, should the server admin misplace the container end token, the
server will not start, complaining with this error message:
Syntax error on line 54 of httpd.conf:
</MyContainer> outside a <MyContainer> container
=head3 C<Apache::FLAG>
When C<Apache::FLAG> is used, Apache will only allow the argument to
be one of two values, C<On> or C<Off>. This string value will be
converted into an integer, C<1> if the flag is C<On>, C<0> if it is
C<Off>. If the configuration argument is anything other than C<On> or
C<Off>, Apache will complain:
Syntax error on line 73 of httpd.conf:
MyFlag must be On or Off
For example:
sub MyFlag {
my($self, $parms, $arg) = @_;
$self->{MyFlag} = $arg; # 1 or 0
}
=head2 Enabling the New Configuration Directives
As seen in the first example, the module needs to be loaded before the
new directives can be used. A special directive C<PerlLoadModule> is
used for this purpose. For example:
PerlLoadModule MyApache::MyParameters
This directive is similar to C<PerlModule>, but it require()'s the
Perl module immediately, causing an early mod_perl startup. After
loading the module it let's Apache know of the new directives and
installs the callbacks to be called when the corresponding directives
are encountered.
=head2 Creating and Merging Configuration Objects
By default mod_perl creates a simple hash to store each container's
configuration values, which are populated by directive callbacks,
invoked when the I<httpd.conf> and the I<.htaccess> files are parsed
and the corresponding directive are encountered. It's possible to
prepopulate the hash entries when the data structure is created, e.g.,
to provide reasonable default values for cases where they weren't set
in the configuration file. To accomplish that the optional
C<L<SERVER_CREATE|/C_SERVER_CREATE_>> and
C<L<DIR_CREATE|/C_DIR_CREATE_>> functions can be supplied.
When a request is mapped to a container, Apache checks if that
container has any ancestor containers. If that's the case, it allows
mod_perl to call special merging functions, which decide whether
configurations in the parent containers should be inherited, appended
or overriden in the child container. The custom configuration module
can supply custom merging functions
C<L<SERVER_MERGE|/C_SERVER_MERGE_>> and C<L<DIR_MERGE|/C_DIR_MERGE_>>,
which can override the default behavior. If these functions are not
supplied the following default behavior takes place: The child
container inherits its parent configuration, unless it specifies its
own and then it overrides its parent configuration.
=head3 C<SERVER_CREATE>
C<SERVER_CREATE> is called once for the main server, and once more for
each virtual host defined in I<httpd.conf>. It's called with two
arguments: C<$class>, the package name it was created in and C<$parms>
the already familiar C<Apache::CmdParms> object. The object is
expected to return a reference to a blessed hash, which will be used
by configuration directive callbacks to set the values passed by the
user in the configuration file. But it's possible to preset some
values here:
For example:
package MyApache::MyParameters;
...
our @APACHE_MODULE_COMMANDS = (...);
...
sub SERVER_CREATE {
my($class, $parms) = @_;
#warn "$class->SERVER_CREATE\n";
return bless {
name => __PACKAGE__,
}, $class;
}
To retrieve that value later, you can use:
my $srv_cfg = $self->get_config($s);
print $srv_cfg->{name}
=head3 C<SERVER_MERGE>
During the configuration parsing virtual hosts are given a chance to
inherit the configuration from the main host, append to or override
it. The C<SERVER_MERGE> subroutine can be supplied to override the
default behavior, which simply overrides the main server's
configuration.
The custom subroutine accepts two arguments: C<$base>, the reference
to the main server configuration object, and C<$add>, the reference to
a virtual host configuration object. It's expected to return a similar
object after performing the merge of the two objects it has received.
The following example implements different merging rules for different
keys.
package MyApache::MyParametersMath;
...
our @APACHE_MODULE_COMMANDS = (...);
...
sub SERVER_MERGE {
my($base, $add) = @_;
#warn "$class->SERVER_CREATE\n";
my %mrg = %$base;
for my $key (keys %$add) {
if ($key eq 'Plus') {
$mrg{$key} = $base->{$key}||0 + $add->{$key};
}
else ($key eq 'Minus') {
$mrg{$key} = $base->{$key}||0 - $add->{$key};
}
else {
$mrg{$key} = $add->{$key}; # override
}
$mrg{$_} = $_ eq 'Append' ?
}
for (keys %$base, keys
return
return bless {
name => __PACKAGE__,
}, $class;
}
=head3 C<DIR_CREATE>
=head3 C<DIR_MERGE>
NotifyError [On Off]
NotifyErrorEmail email_address
=head1 Maintainers
Maintainer is the person(s) you should contact with updates,
corrections and patches.
=over
=item *
Stas Bekman E<lt>stas (at) stason.orgE<gt>
=back
=head1 Authors
=over
=item *
Stas Bekman E<lt>stas (at) stason.orgE<gt>
=back
Only the major authors are listed above. For contributors see the
Changes file.
=cut
1.17 +1 -0 modperl-docs/src/docs/2.0/user/config.cfg
Index: config.cfg
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/config.cfg,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- config.cfg 5 Dec 2002 08:56:10 -0000 1.16
+++ config.cfg 9 Dec 2002 16:47:07 -0000 1.17
@@ -20,6 +20,7 @@
chapters => [qw(
install/install.pod
config/config.pod
+ config/custom.pod
)],
group => 'Coding',
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]