Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RewriteCond to match query string parameters in any order

I have a URL which may contain three parameters:

  1. ?category=computers
  2. &subcategory=laptops
  3. &product=dell-inspiron-15

I need 301 redirect this URL to its friendly version:

http://store.example.com/computers/laptops/dell-inspiron-15/

I have this but cannot make it to work if the query string parameters are in any other order:

RewriteCond %{QUERY_STRING} ^category=(\w+)&subcategory=(\w+)&product=(\w+) [NC]
RewriteRule ^index\.php$ http://store.example.com/%1/%2/%3/? [R,L]
like image 806
TrueBlue Avatar asked Jan 13 '13 19:01

TrueBlue


People also ask

What is RewriteCond in htaccess?

htaccess rewrite rules can be used to direct requests for one subdirectory to a different location, such as an alternative subdirectory or even the domain root. In this example, requests to http://mydomain.com/folder1/ will be automatically redirected to http://mydomain.com/folder2/.

What is NC in RewriteCond?

NC = nocase means regardless of the case of the incoming referrer traffic match with the given pattern. See Apache [NC|nocase] flag.

What is RewriteCond in Apache?

RewriteCond is an apache mod-rewite directive which is used for conditional URL rewriting on Apache server. We use RewriteCond along with RewriteRule%{HTTP_HOST} , %{HTTPS} etc.


1 Answers

You can achieve this with multiple steps, by detecting one parameter and then forwarding to the next step and then redirecting to the final destination

RewriteEngine On

RewriteCond %{QUERY_STRING} ^category=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &category=([^&]+) [NC]
RewriteRule ^index\.php$ $0/%1

RewriteCond %{QUERY_STRING} ^subcategory=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &subcategory=([^&]+) [NC]
RewriteRule ^index\.php/[^/]+$ $0/%1

RewriteCond %{QUERY_STRING} ^product=([^&]+) [NC,OR]
RewriteCond %{QUERY_STRING} &product=([^&]+) [NC]
RewriteRule ^index\.php/([^/]+/[^/]+)$ http://store.example.com/$1/%1/? [R,L]

To avoid the OR and double condition, you can use

RewriteCond %{QUERY_STRING} (?:^|&)category=([^&]+) [NC]

as @TrueBlue suggested.

Another approach is to prefix the TestString QUERY_STRING with an ampersand &, and check always

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC]

This technique (prefixing the TestString) can also be used to carry forward already found parameters to the next RewriteCond. This lets us simplify the three rules to just one

RewriteCond &%{QUERY_STRING} &category=([^&]+) [NC]
RewriteCond %1!&%{QUERY_STRING} (.+)!.*&subcategory=([^&]+) [NC]
RewriteCond %1/%2!&%{QUERY_STRING} (.+)!.*&product=([^&]+) [NC]
RewriteRule ^index\.php$ http://store.example.com/%1/%2/? [R,L]

The ! is only used to separate the already found and reordered parameters from the QUERY_STRING.

like image 150
Olaf Dietsche Avatar answered Sep 28 '22 11:09

Olaf Dietsche