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.


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.

  • Thank you for the detailed reasoning around the response. I learned more about mod_alias and mod_rewrite. Unfortunately, the example did not work for me. What ended up happening is it thinks that example.com/datingstories is a member profile and tries to show the page associated with that member (second rewrite) but since that member does not exist, it shows the resulting 'does not exists' page according to the script. I am experimenting with a RewriteCond right before the second line but no success just yet. – E.Hoh Jul 23 '18 at 6:11
  • I added the following just before the second rule RewriteCond %{REQUEST_URI} !^/thedatinggam to prevent the rule from applying for this URL. This seemed to work as it no longer re-directs to the 'does not exists' page. I also changed the order of the original 2 rules around so it now looks likes this RewriteCond %{REQUEST_URI} !^/thedatinggam RewriteRule ^([a-zA-Z0-9_-]+)$ showprofile.php?username=$1 [L] RewriteRule ^/thedatinggam /blog/category/relationships/thedatinggam/ [R=301,L] However, the first rule does not seem to work, I now get a 404 error. – E.Hoh Jul 23 '18 at 6:41
  • I am using the 'thedatinggam' in place of 'datingstories' (in comment above). I don't think it makes a difference as I also tried it with the original with the same result. – E.Hoh Jul 23 '18 at 6:58
  • Given just the two directives above then it should not be possible for the 2nd RewriteRule to be processed for a /datingstories request. So, if it is being seen as a "member profile", then either something else is doing that (a conflict with other directives perhaps) or you are seeing a cached response? The RewriteCond directive would only be required if you did change the order of these rules. But changing the order does not seem to make sense (in fact, that would result in a similar problem you had in the beginning) - you should have the most specific rules first. – MrWhite Jul 23 '18 at 8:52
  • Presumably these directives are before the WordPress front-controller? – MrWhite Jul 23 '18 at 8:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.