We have had our Website running on an older Apache2 instance with a large .htaccess
file for redirects of old URLs to new ones. Since we have a lot of equal sub-URLs the redirect looks like this:
RewriteRule ^(.*)old/url(.*)$ new/url [L,R=301]
This worked like a charm.
For example www.example.com/a/old/url
got redirected to www.example.com/a/new/url
and also worked for /b/
or /c/
.
With the new Apache (2.4.54) the redirect doesn't work as expected since it redirects as follows:
www.example.com/var/www/html/new/url
What am I doing wrong? Why does it place the base path of the website in front?
I've tried to google as good as possible but couldn't find anything. I would expect any weird path that I don't know of is set in the wrong way.
I'm not very deep into .htaccess
which makes it hard to troubleshoot.
CodePudding user response:
RewriteRule ^(.*)old/url(.*)$ new/url [L,R=301]
This worked like a charm.
For example
www.example.com/a/old/url
got redirected towww.example.com/a/new/url
and also worked for/b/
or/c/
.
It would only do that if you also had a RewriteBase /a
directive defined elsewhere in the config file. (Although it's not clear how it would work the same for /b/
or /c/
, unless you have other directives that are helping. Unless you mean that it redirects from /b/
or /c/
to /a/
? In which case, the RewriteBase
directive alone is what is enabling this to work.)
With the new Apache (2.4.54) the redirect doesn't work as expected since it redirects as follows:
www.example.com/var/www/html/new/url
That will happen if RewriteBase
is not defined as mentioned above.
This applies to both Apache 2.2 and 2.4.
However, it's also possible that RewriteBase
is/was defined in a parent config and RewriteOptions MergeBase
was set (which propagates the setting to child configs). A further complication is that in later versions of Apache 2.2 (specifically 2.2.23 and later) and early versions of Apache 2.4 (specifically 2.4.0 to 2.4.3) this was actually the default (arguably buggy) behavior. So, if you are upgrading from one of these "buggy" versions of Apache, it's possible this was "just working".
The RewriteBase
directive defines the URL-path that is prefixed to relative substitution strings (new/url
is a relative substitution string). If no RewriteBase
is defined then the directory-prefix (ie. the absolute file-path of where the .htaccess
file is located) is added back - which is resulting in your malformed redirect.
For external "redirects" it is often preferable to use a root-relative (starting with a slash) or absolute (scheme hostname) substitution string. For example:
RewriteRule ^(.*)old/url(.*)$ /a/new/url [L,R=301]
The above is no longer dependent on the RewriteBase
directive, since the substitution string (ie. /a/new/url
) is no longer relative.
However, ^(.*)old/url(.*)$
is the same as simply old/url
, which is rather too general. Perhaps something like the following would be preferable:
RewriteRule ^(a|b|c)/old/url /a/new/url [L,R=301]
The above redirects /a/old/url
or /b/old/url
or /c/old/url<anything>
to /a/new/url
.
OR, redirect to the same URL-path (ie. a
, b
or c
) using a backreference:
RewriteRule ^(a|b|c)/old/url /$1/new/url [L,R=301]
You will need to clear your browser cache before testing, since the erroneous 301 (permanent) redirect will have been cached by the browser (and possibly any intermediary caches). Test first with 302 (temporary) redirects to avoid potential caching issues.