Reputation:
I have two requirements;
/product/12345
is internally redirected to /product/product.php?product=12345
./product/product.php
in the URL bar, it is redirected to /product/
for tidiness.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
Reputation: 4688
There probably exist other solutions, but it works if you change two things:
RewriteRule
that checks if the query string is empty, i.e. product/product.php
without query string redirects to /product/
.(.*)
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
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