1

In the document root, I put an .htaccess with:

ErrorDocument 404 /error.php

Since this is in a .htaccess file, Apache looks for error.php in the relative path, so I can put different error.php files in different subfolders to get it to execute different error.php:

request /app1/not-exists.txt : yields /app1/error.php
request /app2/not-exists.txt : yields /app2/error.php
request /not-exists/not-exists.txt : yields /error.php

This is desired behavior. However,

request /not-exists/app1/not-exists.txt : yields /app1/error.php
request /app2/app1/not-exists.txt : yields /app1/error.php

This does not seem like expected behavior. I expected:

request /not-exists/app1/not-exists.txt : yields /error.php
request /app2/app1/not-exists.txt : yields /app2/error.php (or maybe /error.php)

or at worst, some generic Apache error handling. Am I misunderstanding what Apache is supposed to do here? The documentation doesn't seem to make this clear.

1 Answer 1

1

I think your misunderstanding here is the relative pathing.

.htaccess files don't have any special behavior that causes paths to be relative; they're essentially the same thing as a <Directory> block in terms of configuration behavior.

ErrorDocument doesn't have any concept of context; when you enter a path like /error.php that's always assumed to be relative to the document root, regardless of where it's configured. mod_rewrite configuration in a <Directory> block or .htaccess file uses relative paths, which is probably what you're thinking of for that behavior.

A couple options for how you could implement this.. you could have a single error.php that pulls in content from the per-app error files depending on the request path?

Or you could just use mod_rewrite to get the desired error page picking behavior (getting the logic to match what you're looking for is a bit of a complicated mess, though):

<Directory /path/to/docroot>
    # First, we'll have a rule that will handle looking for an error.php in
    # the app directory that the request is in...
    # Not a file or a directory that exists:
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # Capture the application directory that we're trying to load from (if
    # there is one) for use in the next rule:
    RewriteCond %{REQUEST_FILENAME} ^/path/to/docroot/([^/]+)/
    # Check if an error.php exists in that directory;
    RewriteCond /path/to/docroot/%1/error.php -f
    # Send the response to the error page.  It should set the 404 response code.
    RewriteRule ^([^/]+)/.*$ $1/error.php [L]

    # Ok, the previous pile of rules didn't apply;  if the user's requesting 
    # a nonexistent resource, then either the user's not in an app subdirectory,
    # or they're in a subdirectory that didn't have an error.php.
    # So, this is a lot simpler:
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^ error.php [L]
</Directory>
7
  • Regarding your line upfront "ErrorDocument doesn't have any concept of context; when you enter a path like /error.php that's always assumed to be relative to the document root" ... why does my first example (/app1/notexists.txt) yield /app1/error.php instead of /error.php?
    – dlo
    Sep 19, 2012 at 19:23
  • @dlo Are you certain that's the behavior that you're seeing? If it is, I suspect that there's something mapping those directories together in some way; you'd need to provide your full config for me to tell you how that's happening. Sep 19, 2012 at 21:01
  • Sorry for the delay--I'd like to close this out and accept your answer, but I have one important question: what settings might affect Apache's "loose" behavior? eg- I just noticed that if I have a page called Page1.php, and if I request Page1 without the extension, the page still gets served. Perhaps that same behavior is causing the directory matching behavior as well, but looking through apache's conf, I don't see anything that would create this behavior--any pointers?
    – dlo
    Oct 9, 2012 at 14:21
  • And btw, it appears DefaultType is text/plain (and there's no ForceType setting)
    – dlo
    Oct 9, 2012 at 14:23
  • Looks like it's probably Multiviews doing the loose mapping... I'll test this out a little later on.
    – dlo
    Oct 9, 2012 at 14:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .