Search code examples
phpapache.htaccess

Stop apache2 from serving files and redirect to specific PHP file to handle the request


I have built a similar framework to Laravel or Express for Node.js and it is working nicely, that is until I make a request to the path that exists on the server.

Let's say I have this file structure:

web/
  |-- index.php # file that should handle ALL requests that come to this project
  |-- .htaccess
  |-- .env # private file that should not be accessible
  |-- test.txt
  .
  .
  .

When I try to request: myweb.com/.env it serves the file or when I define a route in the framework to /test/a it will try to access it and through error: 404 not found.

How can I set up my .htaccess in a way that ALL requests that end up web/ will be redirected to web/index.php no matter if the request points to a valid file path or not.

This is how my .htaccess is set uped at the moment:

<IfModule mod_rewrite.c>
  Options -Indexes
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
</IfModule>

Solution

  • RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
    

    You don't appear to have understood the rule you are currently using. The two negated conditions (RewriteCond directives) prevent requests that map to phyiscal files (-f) and directories (-d) from being routed to /index.php. So, they are naturally left for Apache to serve them as default.

    So, as a first step, you need to remove those two conditions.

    (This is assuming you don't have a front-end proxy that serves your static assets - a common setup theses days. If this is the case then removing the two conditions will have no effect and you will need to configure/remove the proxy as well.)

    However, the remaining rule would then cause a rewrite loop as it will unconditionally rewrite to itself (a URL-path) repeatedly. You can resolve this by rewriting to a file-path (remove the slash prefix) and use the END flag (Apache 2.4) instead of L.

    For example:

    RewriteRule (.*) index.php?path=$1 [QSA,END]
    

    I've also removed the NC flag, which was superfluous and the anchors on the regex, since .* is greedy by default.

    You should also consider redirecting requests to remove index.php AND/OR the path URL parameter, should this be requested directly. (This is left as an exercise for the reader.)

    Reference: