RedirectMatch and Redirect interfering with each other

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 to https://example.com/showprofile.php?username=frank). However, the URL on the browser shows https://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
1

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.

Leave a Comment