Search code examples
apache.htaccessmod-rewrite

htaccess to hide subdirectory without changing base root, and with exception of another subdirectory


I have a website https://example.com

which has 2 subdirectories, https://example.com/admin and https://example.com/store.

  1. I want to hide /store from URL so my requests would look like: https://example.com/shop.php?id=someid
  2. But Also, I want https://example.com/admin/index.php to work.
  3. I found some answers that achieve both 1 and 2 but they change base root so all my css,js, images don't load

So far I have:

RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
RewriteRule ^store/(.*) /$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
RewriteRule !^store/ store%{REQUEST_URI} [L]

This achieves 1 but not 2.


Solution

  • RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
    RewriteRule ^store/(.*) /$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
    RewriteRule !^store/ store%{REQUEST_URI} [L]
    

    In the second rule... exclude the /admin subdirectory (as well as /store) in the RewriteRule pattern. And add a condition to exclude requests that contain a file extension (ie. .css, .js, .png, etc.). For example:

    RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
    RewriteCond %{REQUEST_URI} !\.\w{2,4}$
    RewriteRule !^(store|admin)($|/) store%{REQUEST_URI} [L]
    

    Alternatively (although marginally less efficient), exclude any request that already maps to a physical file:

    RewriteCond %{HTTP_HOST} ^(www\.)?example.com$
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule !^(store|admin)($|/) store%{REQUEST_URI} [L]
    

    This rule assumes you have another .htaccess file in the /store subdirectory that also uses the rewrite engine. (But if that is the case then the first rule isn't actually doing anything.)

    Unless you are hosting multiple domains/sites then you don't need the first condition that checks the requested Host.