I have an ugly filesystem path on the server: example.com/a/b/c/d/e/f/main.html
. For simplicity, I will use example.com/httpdocs/main.html
in the body of this question.
I want that what the user sees is example.com/easy-to-remember
. I will use example.com/abc
in this question.
For reasons out of the question scope, I would like to do that with only the .htaccess
file, not php-routing.
Let's start with the case that works:
RewriteEngine On
# Rewrite abc/ directory for loading of source material
# Rewrite only if there is no actual file or directory that matches this request
# This can especially be useful for loading resources
# because then the full paths won't be redirected if they are correct.
# Note that RewriteRule never sees leading slashes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^abc/(.*)$ httpdocs/$1 [NC,L]
With that, the user can open example.com/abc/main.html
(expressive path) and is shown the page that is internally stored at example.com/httpdocs/main.html
(ugly path). The user never sees the internal path; the url remains /abc/main.html
in their browser.
Up to this point, everything works as intended. The CSS source files, specified in a relative path in main.html
are still loaded correctly.
But maybe main.html
is a very useless name. I'd rather have example.com/abc
as a link, instead of example.com/abc/main.html
. That'd be more expressive and would allow internal changes of the file extension without changing the links.
# Rewrite abc without trailing slash to main.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^abc$ httpdocs/main.html
# PROBLEM: This turns the current url into "example.com/abc", so "./libs"
# is now looked for in "example.com/libs" instead of "example.com/httpdocs/libs"
This rule still works for loading main.html
without displaying that name in the url to the user.
But the relative paths are now resolved wrongly.
/httpdocs/main.html
relies on /httpdocs/libs/source.css
. In the first case, where we access /abc/main.html
, the sources are loaded from /abc/libs/source.css
and these loads are redirected to /httpdocs/libs/source.css
so everything worked fine. In this second case where we access /abc
, the css is loaded from /libs/source.css
instead, omitting the /httpdocs
directory - and that results in a 404, so the page is now not rendered correctly anymore (when accessed in this way).
The obvious solution would be to keep the first case, and if I really don't want to show the name main.html
to the user, I could in addition add a rule that redirects /abc/expressive-name
to /abc/main.html
(or directly to /httpdocs/main.html
).
But I am curious whether there are ways to achieve what I was trying to do without adding a second depth level (another slash something) to the url.
I want to keep the loading of the sources relative, so that if I ever have to move the whole filesystem to another subdomain or so, I can just copy the whole thing over. Without that constraint, I could simply make all loads absolute.