guest@6admin.io:~$

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/42 instead 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.