Mailing List Archive

Fixing Apache::ReadConfig limitations
Presently, Apache::ReadConfig doesn't seem to provide a way to represent
the order of directives, which limits its usefulness when used with
modules like mod_rewrite that rely on the order of certain directives:

<VirtualHost "*:80">
ServerName example.com
DirectoryRoot /www
<Directory "/www">
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) cgit.cgi/$1 [END,QSA]
</Directory>
</VirtualHost>

This piece of configuration is (AFAIK?) impossible to create using
Apache::ReadConfig, because %VirtualHost and %Directory are unordered
hashes.

Assuming I'm correct about the problem, what could be done to fix it?

My personal idea is to create an additional module created
Apache::ReadConfig::Full (or something), which allows the following:

$Config->push(['VirtualHost', '*:80'] => block(
ServerName => 'example.com',
DirectoryRoot => '/www',
['Directory', '/www'] => block(
RewriteEngine => On,
RewriteCond => '%{REQUEST_FILENAME} !-f',
RewriteCond => '%{REQUEST_FILENAME} !-d',
RewriteRule => '(.*) cgit.cgi/$1 [END,QSA]'
)
);

The `block' function creates an object that amounts to an ordered,
multi-value hash a la Hash::MultiValue. (The global $Config variable is
the same type of object.)

Before I start looking into the possibility of creating such an
interface, I thought I'd ask here whether my assumptions about
Apache::ReadConfig's limitations are correct.

Best regards
John
Re: Fixing Apache::ReadConfig limitations [ In reply to ]
Doesnt it accept array of array refs for this purpose ?

On Fri, Apr 16, 2021 at 1:10 PM John A. <john@ankarstrom.se> wrote:

> Presently, Apache::ReadConfig doesn't seem to provide a way to represent
> the order of directives, which limits its usefulness when used with
> modules like mod_rewrite that rely on the order of certain directives:
>
> <VirtualHost "*:80">
> ServerName example.com
> DirectoryRoot /www
> <Directory "/www">
> RewriteEngine On
> RewriteCond %{REQUEST_FILENAME} !-f
> RewriteCond %{REQUEST_FILENAME} !-d
> RewriteRule (.*) cgit.cgi/$1 [END,QSA]
> </Directory>
> </VirtualHost>
>
> This piece of configuration is (AFAIK?) impossible to create using
> Apache::ReadConfig, because %VirtualHost and %Directory are unordered
> hashes.
>
> Assuming I'm correct about the problem, what could be done to fix it?
>
> My personal idea is to create an additional module created
> Apache::ReadConfig::Full (or something), which allows the following:
>
> $Config->push(['VirtualHost', '*:80'] => block(
> ServerName => 'example.com',
> DirectoryRoot => '/www',
> ['Directory', '/www'] => block(
> RewriteEngine => On,
> RewriteCond => '%{REQUEST_FILENAME} !-f',
> RewriteCond => '%{REQUEST_FILENAME} !-d',
> RewriteRule => '(.*) cgit.cgi/$1 [END,QSA]'
> )
> );
>
> The `block' function creates an object that amounts to an ordered,
> multi-value hash a la Hash::MultiValue. (The global $Config variable is
> the same type of object.)
>
> Before I start looking into the possibility of creating such an
> interface, I thought I'd ask here whether my assumptions about
> Apache::ReadConfig's limitations are correct.
>
> Best regards
> John
>
>
Re: Fixing Apache::ReadConfig limitations [ In reply to ]
Den 2021-04-16 kl. 20:42 skrev Mithun Bhattacharya:
> Doesnt it accept array of array refs for this purpose ?

Could you give an example? I'm not sure I follow.

After experimenting a bit, it seems that the following method, with an
array of hash refs, is accepted:

Directory => {
'/www' => [.
{DirectoryIndex => 'cgit.cgi'},
{RewriteEngine => 'On'},
{RewriteCond => '%{REQUEST_FILENAME} !-f'},
{RewriteCond => '%{REQUEST_FILENAME} !-d'},
{RewriteRule => ['(.*) cgit.cgi/$1 [END,QSA]']},
]
}

but the RewriteConds still don't work the way they should. The
RewriteRule applies regardless of the RewriteConds.

I'd love to find a way for this to work.
Re: Fixing Apache::ReadConfig limitations [ In reply to ]
Den 2021-04-16 kl. 23:30 skrev John A.:
> Den 2021-04-16 kl. 20:42 skrev Mithun Bhattacharya:
>> Doesnt it accept array of array refs for this purpose ?
>
> Could you give an example? I'm not sure I follow.

Replying to myself with an update, as I seem to have figured it out!

I saw Tie::IxHash mentioned somewhere and then found a note in the
mod_perl Developer's Cookbook about Tie::DxHash, which provides ordered,
multi-value hashes.

And indeed, the following code appears to work perfectly:

use Tie::DxHash;

sub block {
my %hash;
tie %hash, 'Tie::DxHash';
%hash = @_;
return \%hash;
}

$VirtualHost{'*:80'} = {
ServerName => 'git.ankarstrom.se',
DocumentRoot => '/usr/local/www/git/data',
Directory => {
'/usr/local/www/git/data' => block(
DirectoryIndex => 'cgit.cgi',
Options => 'FollowSymLinks ExecCGI',
RewriteEngine => 'On',
RewriteCond => '%{REQUEST_FILENAME} !-f',
RewriteCond => '%{REQUEST_FILENAME} !-d',
RewriteRule => '(.*) cgit.cgi/$1 [END,QSA]',
Require => 'all granted'
)
}
};

Neat!