0

I need to have my Apache web-server serve a lot of sites through <Location /> structures. The last thing I want is a massive file with every single <Location /> structure for every single site in there (not even a generated one). I've been looking into mod_rewrite and some of the mass virtual hosting modules available for Apache but, unfortunately, I did not find what I was looking for.

The other day I was looking into mod_perl and as I understand it, I can use mod_perl to 'script' the Apache web server. This made me wonder if this is the solution I've been looking for? I've been searching around for specific examples to my problem but I can't seem to find anything specific.

My question is, to what extend can I have mod_perl generate my <Location /> structures at request time and what sort of variables do I have access to while doing this?

UPDATE:

Just for clarity I'd like to give an example of the sort of thing that I'm trying to do. I know that the following example is not correct but I'm looking for a way to do something like this (at request time):

<Location /$1/$2>
   AuthType Basic
   AuthName "Secure area"
   AuthUserFile /sites/$1/$2/users.file
</location>

So what I want is; Imagine that $1 is the name of a department and that $2 is the name of a project. If I would go the the url mydomain.com/financial/accounts that the users.file from the directory /sites/financial/accounts is used. Every location has a different users.file and if a url doesn't translate to a file system path, a normal 404 is shown or it just won't work. This way I can create a single <location /> pattern without having to maintain a large amount of <location />s and to necessity to reload the server every time I make a change.

Luke
  • 3,826
  • 8
  • 36
  • 40

3 Answers3

1

Did you mean directing HTTP requests according to the site to a different DocumentRoot, ScriptAlias and CustomLog, or do you need something more complex? Could you please provide more details about your Location directives?

Something worth trying might be mod_macro (http://www.coelho.net/mod_macro/)

zarkdav
  • 470
  • 2
  • 4
  • mod_macro might be something but it still needs a definition for every location (although it's much less). It also needs a reload or the server every time you add a new definition. – Luke Jun 11 '09 at 07:18
1

I have not tried your specific use case, but you might want to experiment with mod_perl and:

<Perl>
foreach (</sites/*/*/users.file>) {
    my $loc = $_;
    $loc =~ s/^\/sites(.*)\/users\.file/$1/;
    $Location{$loc} = {
        AuthType => "Basic",
        AuthName => "Secure area",
        AuthUserFile => $_,
    };
}
</Perl>

You will still have to reload Apache each time you add a new "users.file" though. If you really need to do it dynamically, you should build a PerlAuthenHandler instead:

<Location /> # we need for any request to the site
    PerlAuthenHandler MyApache2::DynamicAuthUserFile
    AuthType Basic
    AuthName "Secure area"
</Location>

and a MyApache2/DynamicAuthUserFile.pm script similar to this one:

package MyApache2::DynamicAuthUserFile;

use strict;
use warnings;

use Apache::RequestRec ();
use Apache::Access ();

use Apache::Const -compile => qw(OK DECLINED);

sub handler {
    my $r = shift;
    my ($status, $password) = $r->get_basic_auth_pw;
    return $status if $status != Apache::OK;
    my $user = $r->user;

    my $file = $r->uri;
    $file =~ s|^/sites/([^/]*/[^/])*|$1/users.file|;

    if (open(P, $file)) {
        while (<P>) {
            chomp;
            next if /^#/;
            my ($name,$saved_pw) = split /:/;
            next if $user ne $name;
            if ($saved_pw ne crypt($passwd,$saved_pw)) {
                last;
            }
            return Apache::Const::OK;
        }
        close P;
    }

    return Apache::Const::DECLINED;
}

1;
zarkdav
  • 470
  • 2
  • 4
  • Thanks for this. It's not a 100% answer to my question but it's probably the best answer I will get and at least this will give me some context to investigate this further. – Luke Jun 11 '09 at 21:41
0

Have you already looked at using <LocationMatch>?

It's the regex big brother of <Location>. If there is enough structure to your existing directives then it should be possible to match them with a single regex.

Dan Carley
  • 25,617
  • 5
  • 53
  • 70