I'm trying to write .htaccess code that will ignore the final subdirectory of a URL, route to the directory before that final subdirectory, but leave the URL intact.
This is in the context of an SPA in which I use JavaScript for routing.
If I navigate to directory xxx, which could be nested arbitrarily deeply:
https://my-site/[subdirectories]/xxx
...then when clicking on relative links within the xxx directory, such as to:
./aaa
./bbb
./ccc
...which would correspond to (and produce URLs of):
https://my-site/[subdirectories]/xxx/aaa
https://my-site/[subdirectories]/xxx/bbb
https://my-site/[subdirectories]/xxx/ccc
...then the JavaScript will detect the change in the URL and bring up the content for the "virtual" subdirectories aaa
, bbb
, ccc
. Fine and dandy.
However, if I go to any of those URLs directly, i.e., by entering the URL directly, rather than using navigation within the site, then my site throws a 404 error, as the aaa
, bbb
, and ccc
are not actual subdirectories. They are "virtual" subdirectories, not corresponding to actual folders on the server, and thus the error is thrown.
I want to write an .htaccess routine that will detect an initial navigation (direct opening of):
https://my-site/[subdirectories]/xxx/aaa
https://my-site/[subdirectories]/xxx/bbb
https://my-site/[subdirectories]/xxx/ccc
etc.
...and simply open this location:
https://my-site/[subdirectories]/xxx
...but preserve the "virtual" subdirectory on the end (aaa
, bbb
, ccc
) in the URL as displayed in the URL bar. My JavaScript will take over from there to bring in the desired content for aaa
, bbb
, ccc
. (And this works fine after first navigating to https://my-site/[subdirectories]/xxx
directly and then simply clicking on links to aaa
, bbb
, ccc
; it's going to any of those "subdirectories" directly that's the problem.)
Can this be done with .htaccess? I'm struggling.
The trick is to craft a rewrite rule that specifies a file for the destination content.
If the subdirectory names are known, and for this example they are aaa
, bbb
, and ccc
, then the following rule opens the index.html file in the subdirectory while leaving the URL intact:
RewriteEngine on
# If it's not an actual directory...
RewriteCond %{REQUEST_FILENAME} !-d
# If it's not an actual file...
RewriteCond %{REQUEST_FILENAME} !-f
# Provided aaa, bbb, and ccc are the known subdirectories,
# and (.+) represents ANY text that follows (i.e., any deeper
# subdirectory structure), then $1/index.html will route to
# the index.html file in whichever folder of the aaa|bbb|ccc list
# that is provided:
RewriteRule ^(aaa|bbb|ccc)/(.+)$ $1/index.html [L]