I have the following lines in my .htaccess
(there are other lines but these two are next to each other)
RedirectMatch 301 ^/datingstories https://example.com/blog/category/relationships/datingstories/
RewriteRule ^([a-zA-Z0-9_-]+)$ showprofile.php?username=$1
- There is a WordPress blog component to the site (under
/blog
) as well as a
membership and profile pages built outside of WordPress. - The first line is a simpler way to access a specific set of blogs in a sub-category i.e.
https://example.com/datingstories
translates to the dating sub-category of the blog. This is also shared externally (which is why I wanted the shorter URL) - The second line translates sitename/username to
sitename/showprofile.php?username=username
. There are member profile
pages on the site and the URL is simplified (i.e.
https://example.com/frank
redirects tohttps://example.com/showprofile.php?username=frank
). However, the URL on the browser showshttps://example.com/frank
The issue is when https://example.com/datingstories
is click/linked to, the resulting URL is https://example.com/blog/category/relationships/datingstories/?username=dating
While the page still loads, is there any way of preventing the ?username=dating
from showing as part of the resulting URL. I think the second .htaccess
rule is being applied but I am not sure how since showprofile.php
is not showing up in the resulting URL.
Also, ideally, it would be great if the resulting page shows the shorter URL rather than the longer one.
I appreciate your time in looking and responding to this.
1 Answer
RedirectMatch and Redirect interfering with each other
In the example you’ve given, RedirectMatch
(mod_alias) and RewriteRule
(mod_rewrite) are “interfering with each other”, not Redirect
. Redirect
is a mod_alias directive, that works with RedirectMatch
– so you wouldn’t necessarily expect these to conflict in this way.
As mentioned above, RewriteRule
is a mod_rewrite directive, whereas RedirectMatch
(and Redirect
) are mod_alias directives. Different Apache modules execute independently and at different times during the request, regardless of the apparent order in your .htaccess
file. In the case of mod_alias and mod_rewrite, mod_rewrite always executes first.
So, in your example, the RewriteRule
(2nd directive) will be processed before the RedirectMatch
directive that precedes it – since they both match the URL /datingstories
. Processing then continues through the file and the whole process starts over for a 2nd pass, when the first mod_alias RedirectMatch
redirects the URL (RedirectMatch
matches against the URL in the request, not the rewritten URL. So, this matches /datingstories
again, not showprofile.php
– the rewritten URL). This replaces the rewritten URL-path (showprofile.php
) but keeps the query string (?username=dating
). (However, it’s not clear from the directives you posted, why datingstories
would get truncated to dating
in the URL parameter – maybe there is a conflict with other directives.) The earlier rewrite is converted to an external redirect after the 301 HTTP status is applied.
The lesson here is that you should never mix redirects / rewrites from both modules – in order to avoid confusing conflicts such as this. Since WordPress uses mod_rewrite for its front-controller, you would ideally use mod_rewrite throughout. So, you should convert any mod_alias RedirectMatch
(and Redirect
) directives to use mod_rewrite RewriteRule
instead.
For example:
RewriteRule ^datingstories /blog/category/relationships/datingstories/ [R=301,L]
RewriteRule ^([a-zA-Z0-9_-]+)$ showprofile.php?username=$1 [L]
And don’t neglect the L
flag – to stop further processing (current pass through the file) when required.