2

TL;DR: My URL rewriting breaks if a subdirectory without a file is requested. Instead of loading a default home page as expected, I'm getting a 403 Forbidden error.

I'm using Apache URL rewriting to build a site using the Front Controller pattern. So far, my .htaccess looks like this:

Options -Indexes
RewriteCond %{REQUEST_URI} ^/(subdir|subdir/.*|subdir2|subdir2/.*).*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+) index.php?request=$1 [QSA]

So this is working for all requests except requests for subdirectories:

  • mydomain.com/ results in ->

    • mydomain.com/index.php with home.inc content
  • mydomain.com/page1 results in ->

    • mydomain.com/index.php with /pages/page1.inc content
  • mydomain.com/subdir/ results in ->

    • 403 Forbidden
  • mydomain.com/subdir/page1 results in ->

    • mydomain.com/index.php with /subdir/pages/page1.inc content

More details below that probably don't matter, since the issue is likely in the .htaccess.


In index.php, I'm catching the request and using that to grab the corresponding include page from a directory /pages which has files with the content of each page. Here's the (somewhat simplified) code from index.php:

//grab the actual HTTP request
$request = $_GET['request'];

//if the request has slashes, isolate the directory part into $dir
$slashPos = strrpos($request, "/");
if($slashPos !== false){
    $dir = substr($request, 0, $slashPos) . "/";
    $page = basename($request, ".inc");
} else {
    $dir = "";
    $page = request;
}

//use "home" if no filename is specified.
if($page==""){$page="home";}

//build path to content include
$content = $dir . "pages/" . $page . ".inc";

//output page
require("header.php"); 
require($content ); 
require("footer.php");

This works perfect for the root directory. A request for mydomain.com/page1 results in mydomain.com/index.php being served with the contents of mydomain.com/pages/page1 included.

It also works for pages within a subdirectory: a request for mydomain.com/subdir/page1 results in mydomain.com/index.php being served with the contents of mydomain.com/subdir/pages/page1 included.

It all breaks when the request is for an actual directory. So mydomain.com/subdir/ returns 403 Forbidden. Why is it doing that? I expect it to load $dir with subdir and $page with home (I set as a default for when $page=="").

Yes, Options -Indexes is probably causing the 403, but why only on subdirectories? It doesn't 403 on root. And the line RewriteCond %{REQUEST_URI} ^/(subdir|subdir/.*|subdir2|subdir2/.*).*$ in .htaccess should catch it, right?

lotstolearn
  • 91
  • 10

1 Answers1

0

Ok, I figured it out. The problem is that subdir wasn't actually at web root. My entire site is actually working in its own subdirectory. In other words, I wasn't working in

mydomain.com/

as the root, I was working in

mydomain.com/mydivision/

as a root. So obviously in this line:

RewriteCond %{REQUEST_URI} ^/(subdir|subdir/.*|subdir2|subdir2/.*).*$

the ^ made it look for subdir at the actual webroot. To fix I removed ^ or add my actual subdomain to that line after ^.

lotstolearn
  • 91
  • 10