Back to blog

Friendly URLs with .htaccess: definitive guide from a real WHOIS migration

3/2/2026 · 2 min · Infrastructure

Share

Turning URLs like ?d=example.com&page=wsget into clean paths such as /tool/whois/info/example.com/197 is not only a visual improvement. In real operations, this affects SEO authority, request traceability, route predictability, and long-term maintainability.

This article documents the exact production procedure I used to migrate a WHOIS tool from query-string routing to friendly URLs while preserving backend PHP parameters and legacy compatibility.

1) Initial problem

Legacy URL:

https://example.com/tool/whois/?d=domain1.com

Target route model:

  1. base domain route:
  1. info route:
  1. info route with record id:

Hard requirements:

2) Technical diagnosis

Before writing rules, I validated typical rewrite failure points:

  1. generic rule matching before specific rule
  2. conflict between external redirect and internal rewrite
  3. old query string leaking into canonical URL
  4. permissive regex causing wrong captures

Validation command:

apachectl -t

3) Rule design principle

Stable model used in production:

  1. external 301 redirects first (legacy -> new)
  2. internal rewrites second (new route -> index.php?page=...)

This prevents canonical drift and accidental early captures.

4) Internal rewrite rules

To capture domain safely, I used ([^/]+).

RewriteRule ^tool/whois/([^/]+)/?$ index.php?page=whois&d=$1 [L,QSA]

Full internal layer:

RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA]
RewriteRule ^tool/whois/info/([^/]+)/?$ index.php?page=wsinf&d=$1 [L,QSA]
RewriteRule ^tool/whois/?$ index.php?page=whois [L,QSA]

5) Legacy 301 redirects

For old links containing page=wsinf, I consolidated to canonical friendly URLs with explicit query-string cleanup.

RewriteCond %{QUERY_STRING} ^([^&]+)&page=wsinf$ [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1? [R=301,L]

The trailing ? in destination is critical to drop old query parameters.

6) Final .htaccess used

RewriteEngine On
RewriteBase /

# 1) Legacy to canonical redirects
RewriteCond %{QUERY_STRING} ^page=wsget&id=([^&]+)$ [NC]
RewriteRule ^tool/whois/info/([^/]+)/?$ tool/whois/info/$1/%1? [R=301,L]

RewriteCond %{QUERY_STRING} ^([^&]+)&page=wsinf$ [NC]
RewriteRule ^tool/whois/?$ tool/whois/info/%1? [R=301,L]

# 2) Internal routing
RewriteRule ^tool/whois/info/([^/]+)/([^/]+)/?$ index.php?page=wsget&d=$1&id=$2 [L,QSA]
RewriteRule ^tool/whois/info/([^/]+)/?$ index.php?page=wsinf&d=$1 [L,QSA]
RewriteRule ^tool/whois/([^/]+)/?$ index.php?page=whois&d=$1 [L,QSA]
RewriteRule ^tool/whois/?$ index.php?page=whois [L,QSA]

7) Production validation checklist

  1. Apache syntax:
apachectl -t
  1. Redirect/canonical headers:
curl -I "https://example.com/tool/whois/?domain1.com&page=wsinf"
curl -I "https://example.com/tool/whois/info/domain1.com"
  1. App-level parameter validation:
  1. Loop detection:
curl -IL "https://example.com/tool/whois/?domain1.com&page=wsinf"
  1. Trailing slash behavior:

8) Troubleshooting notes from field execution

8.1 Generic rule catching specific route

Fix: sort rules from most specific to most generic.

8.2 Browser cache hiding changes

Fix: use private session and curl for deterministic checks.

8.3 Legacy query string surviving redirect

Fix: append ? in redirect destination to clear old query params.

9) Operational best practices

Technical conclusion

Friendly URL migration with Apache .htaccess is a routing refactor, not a cosmetic change. With a two-stage model (301 canonicalization + internal rewrite), you can preserve legacy compatibility, improve SEO, and keep backend business parameters stable under production load.

CC BY-NC

This post is licensed under CC BY-NC.

Comments

Join the discussion below.