Apache Filesystem Cascading Howto
From M@Wiki

Main Page | About | Help | FAQ | Special pages | Log in

Categories: Apache | Perl
Printable version | Disclaimers | Privacy policy


Sometimes you need to merge multiple filesystem paths into the same webspace. Maybe you need to partition web volumes out for volume management purposes, maybe some data is on your SAN and other is on local disk? No matter, this solution will fix it AND add case-insensitivity using a previously-described method, all in one.

NOTE: This solution is known to work on Apache 2.2 using mod_perl 2.0 - It may not work on older versions of either.

Filesystem Cascading w/ Bonus Fix Case

Most of the time, you just want to fix the case when people type it incorrectly into their webbrowser, or someone mis-linked something. The below script, when installed as a PerlTransHandler will do exactly that. If the request exists, the handler passes on and doesn't do anything- But if it doesn't, it recurses through the request URI and case-insensitively builds a URI that does exist.

httpd.conf Changes

You'll need to make sure that for each of the entries in @docroots below, there is a valid httpd.con <Directory> container giving Apache the right necessary to serve files out of those locations.

In your httpd.conf you'll want:

PerlModule Apache2::RequestUtil
PerlModule fsmerge
PerlTransHandler fsmerge

Handler Code (Perl)

In /usr/lib/perl5/site_perl/fsmerge.pm the below should be:

package fsmerge;

use Apache2::Const qw(DECLINED);
use Apache2::RequestUtil ();

# This list will be processed IN ORDER, the first thing matching wins.
my @docroots = (
    "/mnt/mount1",
    "/mnt/mount2",
    "/san/raid/somevolume",
    );

sub handler {
   my $r = shift;
   my $sofar=0;
   for(@docroots) {
      my $dr=$_; # This docroot
      my $file=$dr . $r->uri();
      $sofar=0;
      my $newuri=$dr; # $newuri is the uri we're building
      unless(-e $file) {
         # File doesn't exist, let's try to find it!
         my @uribits=split(/\//,$r->uri());
         shift @uribits; # shift off the beginning ''
         for(@uribits) {
            my $bit=$_;
            $bit =~ s/\(|\)|\`//g; # stupid url tricks
            $sofar=0; # reset sofar, so we know if we're still on track
            opendir(FD,$newuri) or last;
            for(readdir(FD)) {
               my $dthing=$_;
               if($dthing =~ /^\./) { next; } # safety first;
               if($dthing =~ /^$bit$/i) { # case-insenstive pattern match
                  # We have a match!
                  $sofar=1;
                  $newuri .= "/$dthing";
                  last;
               }
            }
            closedir(FD);
            unless($sofar) { last; } # we missed this bit, don't bother recursing further
          }
       } else {
          # Woo hoo!
          $sofar=1;
          $newuri=$file;
       }

       if($sofar) {
          # We made it!
          $newuri =~ s/^$dr//; # strip off the document_root from the new uri
          $r->uri($newuri); # Set the uri to the new uri
          $r->document_root($dr); # Set the new doc root
          last;
       } # else we can't do anything...
   }
   return DECLINED; # Pass it on, regardless of the outcome
}
1;

Retrieved from "http://mattwork.potsdam.edu/projects/wiki/index.php/Apache_Filesystem_Cascading_Howto"

This page has been accessed 1,679 times. This page was last modified 01:02, 1 November 2006.