1

I want https://www.example.com/somePage.php?id=1234 to be redirected to https://www.example.com/tool/1234 (so that legacy links and bookmarks work).

I think I am close, but this appears to not work...

RewriteRule ^somePage.php?toolid=([0-9]+)$ /tool/$1 [R=301,L]

What's wrong here?

MrWhite
  • 11,643
  • 4
  • 25
  • 40
DrDamnit
  • 348
  • 4
  • 16
  • `.htaccess` or directly in your server config? – MrWhite Jan 11 '17 at 18:32
  • Possible duplicate of [Redirect, Change URLs or Redirect HTTP to HTTPS in Apache - Everything You Ever Wanted to Know About Mod\_Rewrite Rules but Were Afraid to Ask](http://serverfault.com/questions/214512/redirect-change-urls-or-redirect-http-to-https-in-apache-everything-you-ever) – Tero Kilkanen Jan 12 '17 at 02:49

1 Answers1

1

You can't match the query string in the RewriteRule pattern. You need to use a RewriteCond directive and compare against the QUERY_STRING server variable.

But also, assuming you have an internal rewrite later in your config file that rewrites back to the (real) ugly URL then you can't do a simple redirect, as it will result in a redirect loop. You need to make sure you only redirect the initial request, not the rewritten URL.

Assuming this is .htaccess, based on your existing RewriteRule pattern, try the following, near the top of your config file:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^toolid=(/d+)$
RewriteRule ^somePage\.php$ /tool/%1 [R=301,L]

Note, however, that your example URLs differ from your code example. I've gone with your code example.

The REDIRECT_STATUS environment variable is empty on the initial request, but gets set to "200" after a successful internal rewrite. So, this avoids a redirect loop in per-directory .htaccess files.

Make sure you've cleared your browser cache, since any erroneous 301s (whilst testing) will have been cached by the browser.

MrWhite
  • 11,643
  • 4
  • 25
  • 40
  • This is very helpful, but it does not appear to be working. I know the .htaccess file is working because this application uses a front controller and is then parsed internally (so we don't need re-write, we use routes in PHP and regular expressions). What's my next step to debug this? – DrDamnit Jan 11 '17 at 21:31
  • The above should match the example URL given, except for the "toolid" vs "id" parameter. The order of directives is important, the above redirect will need to go _before_ your existing rewrites. If you add your complete `.htaccess` file to the question we can have a better look. – MrWhite Jan 11 '17 at 21:48
  • And when you say "does not appear to be working" - what actually happens? Nothing at all? Error? – MrWhite Jan 12 '17 at 07:34
  • "nothing" happens. There is a re-write directive below it that re-writes everything to index.php (front controller). That fires normally. It's like it is skipping over this because of a non-match. – DrDamnit Jan 12 '17 at 13:28
  • The above should redirect a URL of the form `/somePage.php?toolid=1234` (exact match, case-sensitive). Try temporarily removing the first `RewriteCond` directive that checks against `REDIRECT_STATUS`. – MrWhite Jan 12 '17 at 14:11
  • Did anything happen after removing the first _condition_? If you got too many redirects then we need to see why `REDIRECT_STATUS` wasn't working (we can use an alternative and check against `THE_REQUEST`). If still nothing happened then either there is a conflict with existing directives (please include your complete `.htaccess` file in your question) or the _regex pattern_ is simply not matching, in which case you need to confirm the _exact_ URL and pattern you are using. – MrWhite Jan 13 '17 at 11:10