Apache: URL rewriting
mod_rewrite is the Apache module that rewrites URLs on the fly. It transforms /article.php?id=42 into /article/42, redirects old links to new ones and does everything a reverse proxy does not: it modifies the request before it reaches the application.
The basic
RewriteEngine On
RewriteRule ^article/([0-9]+)$ article.php?id=$1 [L]
This rule transforms /article/42 into article.php?id=42 internally (the user sees /article/42, Apache runs article.php?id=42). The [L] means “last rule”: if this rule matches, the following ones are not evaluated.
The rules that matter
# Force www
RewriteCond %{HTTP_HOST} ^mydomain.fr$
RewriteRule ^(.*)$ http://www.mydomain.fr/$1 [R=301,L]
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Block a user-agent
RewriteCond %{HTTP_USER_AGENT} sqlmap [NC]
RewriteRule .* - [F]
# Redirect everything to an index (WordPress pattern)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
The RewriteConds are the conditions: if the condition matches, the following RewriteRule applies. The flags: [R=301,L] = permanent redirect + last rule, [F] = forbidden (403), [NC] = no case.
What it is for
- Clean URLs:
/article/42instead of/article.php?id=42, for SEO and readability; - Massive redirects: old site links to new ones, without touching the application;
- Blocking: scanner user-agents, forbidden HTTP methods, source IPs;
- The “everything to index.php” pattern: this is what WordPress, Drupal and every PHP CMS with URL routing does.
The config is tested with apachectl -t before the restart, because a broken rewrite rule cuts the whole site.