My situation is as follows: I have static files in folder public/
on my local server. Any request that comes in should be forwarded to that folder, but if a file in that folder is accessed directly, it should be either a 404 or redirect to the 'slug'. Example:
Request: /my-file
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file
Request: /public/my-file.html
Should rewrite to: /public/my-file.html
URL should be: http://localhost/my-file
I have the following rules and conditions in my .htaccess
:
RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI}.html -f
RewriteRule ^.*$ /public/$0.html [L,C]
RewriteCond %{REQUEST_URI} ^/public
RewriteRule ^public/(.+).html$ /$1 [R=301,L]
From top to bottom:
- Is
/public/{request}.html
a file? - Rewrite if (1) is true:
/public/{request}.html
, and chain to (3) to prevent a redirect loop - Does the original request start with
/public
? - Rewrite if (3) is true, and original request matches
public/{request}.html
:/{request}
. Also make a301
header, which tells my browser and crawlers the page has moved permanently. The request will run through all the rules again
So, if we do those two requests:
1. Request: /my-file
/public/my-file.html
evaluates to true; the file exists in my folder.- Rewrites to:
/public/my-file.html
, chain to 3 - The original request does not match.
- Skipped
So far, so good; the right file is shown with the URL I want. Request number 2, which is a request for the actual file as it exists in the file structure:
2. Request: /public/my-file.html
public/public/my-file.html.html
evaluates to false, the file does not exist in my folder.- Skipped
- The original request matches: it starts with
/public
- Rewrite
public/my-file.html
to/my-file
, and go from the top.
Now, after (4) in the 2nd example, I'd say that the request matches the 1st example, meaning I get the page I'm looking for with the right URL (because of the 301). But it doesn't work: the URL doesn't change, I'm getting the page I'm looking for but not the URL (which should be /my-file
).
Does anyone have pointers? I think I'm almost there but doing something wrong with the chaining or redirect. Thanks!
Edit
After having tried all kinds of stuff, I finally decided that what I want is probably not possible. I want to redirect an existing file (public/my-file.html
) to a non-existent file (my-file
) visually, but internally I want it to request the existing file path. This will invariably result in a redirect loop, because mod_rewrite just doesn't work that way:
User typed: website.com/my-file
Rewrites to file path: .../wwwroot/public/my-file.html
Internal redirect
Rewriterule found: /public/my-file.html should redirect to my-file
See above.
I haven't come across any comparable situation here on ServerFault or on StackOverflow - usually the rewriting goes to a generic .php
file, not to an existing .html
file.
I marked Krist van Besien's answer as the right one since it pointed me in the right direction for figuring all this out.
Edit 2
In a followup question, the problem was solved by using %{THE_REQUEST}
: See here