Wasim
Wasim

Reputation: 1174

htaccess: generates error if dot(.) exists in query string

I’ve written .htaccess file as follows:

Options +FollowSymLinks

RewriteEngine On

#open the product details page with the Product Number with PN prefix 
RewriteRule ^((products/|product/|)PN[0-9-]+)/?$ product.php?pno=$1 


#open the product search page for a particular category 
RewriteRule ^((bat|ref|acc)[A-Za-z0-9-]+)/?$ search.php?cat=$1 [NC]

#open the product search page for a particular category 
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteRule ^([A-Za-z0-9-_.,]+)/?$ search.php?search =$1  [NC]

RewriteRule !\.(html|php)$ - [S=4]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3 [E=uscor:Yes]
RewriteRule ^([^_]*)_(.*)$ $1-$2 [E=uscor:Yes]
RewriteCond %{ENV:uscor} ^Yes$
  1. It couldn't accept if there is dot(.) in the query string value. Now, it is solved, but can't accept its previous rule.

  2. Furthermore, I want it to rewrite the "URL/product.php?pno=PN123" properly if the URL "URL/products/PN123" or "URL/product/PN123" is given. Please note that it can redirect correctly if "URL/PN123" is given correctly with proper CSS. AND "URL/product/PN123" can also retrieve the data but can't show CSS prperly.

Upvotes: 4

Views: 884

Answers (2)

TerryE
TerryE

Reputation: 10888

You've got a few bugs in your regexps. Load up this checker on your site if you want to play with these.

  • The pattern ^((products/|product/|)PN[0-9-]+)/ does not match "URL/products/PN123" or "URL/product/PN123" or "URL/PN123" and return the PN123 because of the embedded match string and the trailing slash. You can hide the product(s)/ and make the trailing / optional as below.

  • I don't like using the ! prefix in rule patterns, especially when using a grouped parts. Too easy to shoot yourself in the foot. I prefer a cond followed by a null rule or a negative lookahead.

  • Fall-though match rules can trigger the postfix bug so again I avoid them. The engine loops retrying .htaccess files (because they are evaluated in a "Per Directory context") until no match so I find it just a LOT safer to always use the [L] flag
  • Again because of this looping you need to assure that your rules will terminate and its better to do this in a simple transparent manner. In this case you don't seem to want to rewrite URIs which map to real files so why not hoist the -f test to the top and all other rules can then assume that this condition is true.
  • The two search rule mean that the cat=acc123 parameter is used if the request is for /acc123/ etc and search= otherwise. Is this what you want?
  • You need to include the QSA flag unless you want to ignore any existing parameters.
  • The environment variable USCOR (I stick to uppercase) becomes REDIRECT_USCOR on the next pass so this is what you test for. I assume that a rule follows this last cond

Putting these all together gets:

Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /

# The rewrite engine loops in a Per Dir context. We don't remap real files so:

RewriteCond %{REQUEST_FILENAME}       -f
RewriteRule ^                         -                           [L]

# Open the product details page with the Product Number with PN prefix 
RewriteRule ^(?:products?)?(PN\d+)/?$ product.php?pno=$1          [L,NC,QSA]

# Open the product search page for a particular category
RewriteRule ^((?:bat|ref|acc)[A-Za-z0-9-]+)/?$ search.php?cat=$1  [L,NC,QSA]

#open the product search page for a particular category 
RewriteRule ^([A-Za-z0-9-_.,]+)/?$ search.php?search=$1           [L,NC,QSA]

RewriteRule \.(?!(php|html)$)               -                 [S=4,NC]
RewriteRule ^(.*?)_(.*?)_(.*?)_(.*?)_(.*)$  $1-$2-$3-$4-$5    [E=USCOR:Yes, L]
RewriteRule ^(.*?)_(.*?)_(.*?)_(.*)$        $1-$2-$3-$4       [E=USCOR:Yes, L]
RewriteRule ^(.*?)_(.*?)_(.*)$              $1-$2-$3          [E=USCOR:Yes, L]
RewriteRule ^(.*?)_(.*)$                    $1-$2             [E=USCOR:Yes, L]

I am not sure what you want to do with %{ENV:REDIRECT_USCOR} now without the additional rules and logic, though it will be available to the script as $_SERVER["REDIRECT_USCOR'].

Upvotes: 2

anubhava
anubhava

Reputation: 785541

This is your corrected/updated .htaccess, however it would have been better if had written more about your actual requirements:

Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /

#open the product details page with the Product Number with PN prefix 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((products/|product/|)PN[0-9-]+)/?$ product.php?pno=$1 [L,NC,QSA]

#open the product search page for a particular category 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((bat|ref|acc)[A-Za-z0-9-]+)/?$ search.php?cat=$1  [L,NC,QSA]

#open the product search page for a particular category 
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteRule ^([A-Za-z0-9-_.,]+)/?$ search.php?search=$1 [L,NC,QSA]

RewriteRule !\.(html|php)$ - [S=4,NC]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3 [E=uscor:Yes]
RewriteRule ^([^_]*)_(.*)$ $1-$2 [E=uscor:Yes]
RewriteCond %{ENV:uscor} ^Yes$

About your css, js, image file: Make sure your path to css, js etc start with a slash / and not a relative one.

Upvotes: 3

Related Questions