.htaccess Redirect 301 with trailing slash adds trailing slash to destination

Just had my website re-done and am trying to set up redirects in the .htaccess file for links that have changed

This works fine, except it doesn't work for /example/ (with trailing slash on source path)

Redirect 301 /example /example.php

So I added this to account for the trailing slash:

Redirect 301 /example/ /example.php

But that redirects to example.php/ (adds a trailing slash to the destination, which does not work)

Clearly I'm doing this wrong. What is a better way?


But that redirects to example.php/

That is caused by the first (original) rule. Note that the earlier (erroneous) 301 will likely have been cached by the browser. Test with 302 (temporary) redirects to avoid potential caching issues.

The Redirect directive is prefix-matching (whole path segments), and everything after the match is appended to the end of the target URL. So, the first directive redirects:

  • /example to /example.php
  • /example/ to /example.php/ and
  • /example/abc to /example.php/abc

If the directives are ordered like this then they should "work" for the two example URLs posted:

Redirect 301 /example/ /example.php
Redirect 301 /example /example.php

However, the Redirect directive is not really the correct directive to use here, since you need two directives to handle this. (Generally, with the Redirect directive, you need to either include or exclude the trailing slash on both the source and target URLs.)

You could use the RedirectMatch directive instead, which matches using a regex. For example, to handle both with and without a trailing slash:

RedirectMatch 301 ^/example/?$ /example.php

This matches only /example or /example/ and redirects to /example.php.

Redirect and RedirectMatch are both part of mod_alias.

However, if you are already using mod_rewrite then consider using mod_rewrite RewriteRule instead to avoid potential conflicts, since mod_rewrite always runs before mod_alias, despite the apparent order of the directives in .htaccess. For example:

RewriteEngine On

RewriteRule ^example/?$ /example.php [R=301,L]

Note that there is no slash prefix on the RewriteRule pattern when used in .htaccess since the URL-path that the pattern matches against has had the directory-prefix (which always ends with a slash) removed.

Note also that the order of the directives within each module can be important.

Aside: If you've had your website "re-done", why are the "new" URLs of the form /example.php? This would seem to be backward?


UPDATE: I had someone convert the original wordpress website to an (almost) equivalent site that used only HTML and a little javascript and php

You could potentially keep the original WordPress URLs (eg. /example) and internally rewrite the request to the underlying file that handles the request (ie. example.php) instead of externally redirecting. For this you would need to use mod_rewrite. You also need to be linking to the "old" WordPress URLs in your HTML source. eg. /example (and consider canonicalising the trailing slash - redirect to one or the other).

To internally rewrite /example (or /example/) to /example.php you simply need to remove the R flag from the above RewriteRule directive. For example:

RewriteRule ^example/?$ example.php [L]

(I've also removed the slash prefix on the RewriteRule substitution, which is now not required since we are rewriting to a filesystem path.)

Providing you link to /example in your HTML source then the user is unaware that the request is really mapped to example.php.