3

I am in the process of re-building my private blog. I now want to use a hoster with PHP. However, I would like to hide the .php extension and use .html instead. On the other hand, the hoster requires a rewrite to .php to actually run the scripts. So I would like to:

  1. Externally redirect any request for a .php to the corresponding .html URL, so the user does not "see" the PHP URL.

  2. Internally rewrite any request for a .html file to a .php filename to execute the actual PHP script.

The hoster uses Apache with mod_rewrite as far as I can tell.

Basically what I think I need is:

RedirectEngine On
RedirectMatch 301 ^(.*).php$ $1.html
RewriteRule ^(.*).html$ $1.php [L]

However, I get an infinite redirect loop to the .html file. As if the RewriteRule automatically triggers the RedirectMatch again. I also tried various combinations of RewriteRule, RewriteCond and RewriteBase instead of the RedirectMatch, but the redirect then usually goes to some hoster-internal directory structure (like /bla/foo/user/xyz/.../file.html), and RedirectBase shows no effect.

Any help is appreciated!

1 Answer 1

2

For something like this you need to use just mod_rewrite. RedirectMatch is a mod_alias directive so can result in a conflict (different modules run at different times, despite the apparent order in your config file). Regardless, you still need to be careful of redirect/rewrite loops.

# 1. Externally redirect `.php` requests to `.html`
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+)\.php$ /$1.html [R=302,L]

The RewriteCond directive that checks against the REDIRECT_STATUS environment variable prevents the rewritten URL from being redirected (which would result in a redirect loop). REDIRECT_STATUS gets set to "200" (200 OK HTTP Status) after the first rewrite (below).

Change the 302 (temporary) redirect to a 301 when you are sure it's working OK. 301s are cached hard by the browser so can make testing problematic.

Then, perform the internal, much like you had before (remember to escape the dots to match a literal dot):

# 2. Internally rewrite `.html` to `.php`
RewriteRule ^(.+)\.html$ $1.php [L]

As if the RewriteRule automatically triggers the RedirectMatch again.

Yes, this does indeed happen (reason for the RewriteCond directive above). When the URL gets rewritten/changed, the whole process will be repeated until the URL passes through unchanged.

but the redirect then usually goes to some hoster-internal directory structure

This happens when you try to redirect to a relative path in a per-directory (ie. .htaccess) context. The directory-prefix (the internal directory filesystem path) is prefixed back on the rewritten URL. For an external redirect you need to specify an absolute or root-relative URL.

and RedirectBase shows no effect.

Well, a RewriteBase directive would resolve the problem above of redirecting to a relative path. The RewriteBase directive effectively changes the directory-prefix that is added back to relative path substitutions. This is all it does. If you are not using relative path substitutions then it has no effect.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.