I need help from some of you Apache/mod_rewrite experts.
I want to achieve the following effect:
If the user goes to "script.php" he gets a 404 not found error.
If the user goes to "page.htm" he gets the output of script.php.
In other words, I want to hide the fact that script.php exists at all, but still be able to direct its output to page.htm. I am working on a per-directory basis with .htaccess.
This rule works fine by itself:
RewriteRule ^script\.php$ nonexistent.htm
nonexistent.htm doesn't exist, and the user gets 404 if he types "script.php" in the browser.
This rule also works fine by itself:
RewriteRule ^page\.htm$ script.php [T=application/x-httpd-php]
If the user goes to page.htm (which doesn't exist), he gets the output of script.php, but the location bar still says "page.htm".
However, if I combine the rules in the .htaccess file to cover both possibilities it doesn't work:
RewriteRule ^script\.php$ nonexistent.htm [L]
RewriteRule ^page\.htm$ script.php [T=application/x-httpd-php,L]
Notice I added the "L" flags, but now I get a 404 in both cases --> page.htm becomes script.php becomes nonexistent.htm and 404. (I verified this by setting nonexistent.htm to a real page, and it always went there if you went to either page.htm or script.php).
Originally I wanted script.php to become page.htm in the browser but keep the same output, but I ended up with an infinite loop, even with the "L" flags, which I don't understand...
Can anyone explain if what I want is possible or what I'm doing wrong? Why is the rule pointing to the nonexistent page always invoked? According to the docs, they are processed in order, and I'm not using re-directs. (I tried the rules in opposite order, same result.)
Andy Serpa
Snip, no sigs please
(edited by: NFFC at 7:32 am (gmt) on Nov. 21, 2001)
RewriteEngine on
RewriteBase /Test/
RewriteRule ^foo\.html$ error.html [L]
RewriteRule ^bar\.html$ foo.html [L]
I get exactly the same behaviour with only the existance of foo.html - both foo.html and bar.html respond 404.
My working theory is that the rules are parsed twice in this case. Once on the bar.html, internally redirected to foo. Then they are parsed again with foo.html and bring back error.html.
By making error.html a file I'm going to test this.
.... go make a coffee ;) ....
Yep - Now typing bar.html brings back the error.html file contents. So looks like my theory was right - hopefully someone with more mod_rewrite use will be able to confirm this is part of the plan.
I'm investing some time in learning this mod_rewrite thing - it is very cool so far.
%{THE_REQUEST} variable echos the actual request the user put in his browser (note that %{REQUEST_FILENAME} or %{REQUEST_URI}) will NOT work because they get updated internally. So with the new condition, the first rule is only triggered if "script.php" is in the original request from the browser, which makes everything work as desired.
The first rule can now be changed to (with the same RewriteCond as above):
RewriteRule ^script\.php$ page.htm [R,L]
and now the user will get the output of script.php whether he types page.htm or script.php except if he types script.php it will change to page.htm in the browser.
Confusing enough?
My guess is that the original problem is caused by the fact that I'm doing this in .htaccess files on a per-directory basis, which according to the mod_rewrite docs comes rather late in the URL processing process and probably makes the file get processed again after the intial rewriting, effectively negating the [L] flags. Can anyone confirm this? Can anyone even understand this?
In case you're curious why I want to do this in the first place it is because I'm transforming my site from static HTML to PHP/MySQL dynamically generated pages, but want to keep all the same old already linked-to/search-engine friendly .htm files, and I don't want any of the .php files to get "out in the world" accidentally....
Andy Serpa
chessmad@chessopolis.com
Then use mod_rewrite (or robots.txt) to deny access to that directory?
Something like, in your base directory.
RewriteRule ^(.*)\.htm$ php/script.php [T=application/x-httpd-php]
Then in your php directory RewriteRule ^.*\.php /error.html
or a robots.txt file stopping access to the directory and never having any links to it, would also stop the php files getting out.
I'm really just now learning all about PHP/MySQL and the innards of Apache and simply wanted to solve the above problem because it seemed as though it *should* have worked but didn't. Whether or not it is the final best solution for my web site is secondary to the knowledge gained in this case...
I do something similar to this at the start of my script rather than using mod_rewrite
if ($REFERER == page.htm) {
instructions
to
execute
}
else {
header("HTTP/1.0 404 Not Found");
}
Well I sorta lied here, my script actually doesnt use the PHP Referer variable. Since it uses a POST action on a form I just check to see if the variable is set _php isset()_ and has a value but I don't think you would have any problems using Referer here. Also, with the header function you can send a redirect back to page.html with something like this: header("Location: page.htm")
I hope that makes sense (I hope I understood what you are wanting to do hehe)