Hunter Mitchell Hunter Mitchell - 1 month ago 13
PHP Question

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/routes
produces:
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)

Answer

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>