Search code examples
php.htaccessmod-rewritealtorouter

Emulating Node/Express Routes in .htaccess


I have been trying to emulate how nodejs/express work with their routes. I am forwarding all traffic to index.php to process routes (using AltoRouter).

My file struture is something like this:

-/
--public/
  |- assets
  |- ...
--routes/
  |- route.php
  |- ...
--index.php

Take these urls for instance (all should return/redirect 404):

http://testsite.com/routes

http://testsite.com/routes/route.php

http://testsite.com/somefile.php

However only assets should be directly accessible like so (I dont want to include /public/:

http://testsite.com/assets/image.png

http://testsite.com/assets/styles/style.css

This is what I have so far:

# Make sure mod_rewrite is on
<IfModule mod_rewrite.c>
    RewriteEngine on

    # This should allow us to get our assets and keep them public
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)\.(gif|jpg|png|jpeg|css|js|swf)$ /public/$1.$2 [L,NC]

    # Forward other traffic to index.php
    RewriteRule ^.+$ index.php [L]
</IfModule>

One issue i've come accross is going: http://testsite.com/routesproduces: enter image description here

I Guess my main question is anything that isnt in public shouldnt be accessable (not sure if .htacces is the way to go or not)


Solution

  • You don't have to bury your files above web root if you use the right rules. Private files can easily be made inaccessible.

    <IfModule mod_rewrite.c>
        RewriteEngine on
        # transform assets URLs to correct path, and proceed to next rule
        # checking existence in RewriteConds is useless here since public URLs are not 1:1 physical paths
        RewriteRule ^assets/.+ public/$0 [NS,DPI]
        # send *all* URLs to index.php except those that point to an asset file that exists
        RewriteCond $1 !=public/assets/ [OR]
        # change the slash in next condition to your sub-directory if not serving from the web root, e.g. %{DOCUMENT_ROOT}/project/root/$0
        RewriteCond %{DOCUMENT_ROOT}/$0 !-f
        RewriteRule ^((?:[^/]+/){2})?.+ index.php [NS,END]
    </IfModule>