user11813319
user11813319

Reputation:

Rewriting subdirectory to query string parameter

I have two requirements;

Separate, they both work correctly, but together it results in an infinite loop - I know that I'm redirecting from /product/ to /product.php and back again, but the difference is internal vs external and I'm not sure how to distinguish between them.

RewriteEngine On

RewriteRule ^product/product.php /product/ [NC,R=307,END]

RewriteCond %{REQUEST_URI} !^/product/product.php [NC]
RewriteRule ^product/(.*) /product/product.php?product=$1 [NC]

Upvotes: 1

Views: 99

Answers (2)

Freddy
Freddy

Reputation: 4688

There probably exist other solutions, but it works if you change two things:

  1. Add a condition to the first RewriteRule that checks if the query string is empty, i.e. product/product.php without query string redirects to /product/.
  2. Change (.*) in the second RewriteRule to (.+) or ([0-9]+) to only rewrite requests containing a product id (requests to /product/ are not rewritten).
RewriteEngine On

RewriteCond %{QUERY_STRING}        ="" [NC]
RewriteRule ^product/product\.php$ /product/ [NC,R=307,END]

RewriteCond %{REQUEST_URI}  !^/product/product\.php [NC]
RewriteRule ^product/(.+)   /product/product.php?product=$1 [NC]

Upvotes: 1

MrWhite
MrWhite

Reputation: 45829

access /product/product.php in the URL bar, it is redirected to /product/ for tidiness

You might as well also redirect /product/product.php?product=12345 to the corresponding canonical URL (ie. /product/12345) - which you can do all in the same rule. If the product ID is numeric only then you should restrict your regex accordingly - this will also avoid the need for an additional condition.

For example:

# Canonical redirect
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(?:product=(\d*))?$ [NC]
RewriteRule ^product/product\.php$ /product/%1 [NC,R=307,L]

# Rewrite requests from "pretty" URL to underlying filesystem path
RewriteRule ^product/(\d*) /product/product.php?product=$1 [L]

The condition that checks against the REDIRECT_STATUS environment variable is necessary to prevent a redirect loop in this instance since the query string is entirely optional.

By restricting the match to digits-only, we avoid the need for an additional condition on the internal rewrite, product.php won't match. If the product id can contain letters then restrict the pattern to avoid dots (.), eg. ([^./]*).

Only include a NC flag on the internal rewrite if this is strictly necessary, otherwise this potentially creates a duplicate content issue.

Upvotes: 0

Related Questions