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}.htmla 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 a301header, 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.htmlevaluates 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.htmlevaluates to false, the file does not exist in my folder.- Skipped
- The original request matches: it starts with
/public - Rewrite
public/my-file.htmlto/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