mod_rewrite
mod_rewrite is Apache's URL-rewriting engine -- it lets you rewrite an incoming request to a different internal URL based on pattern-matching rules, which is how sites turn /product.php?id=42 into a clean /products/42 in the address bar.In this page:
Enabling the Module
mod_rewrite isn't always on by default. On Ubuntu/Debian, enable it with sudo a2enmod rewrite and reload Apache; on RHEL-family systems it's usually compiled in and just needs LoadModule rewrite_module modules/mod_rewrite.so uncommented in the config.
RewriteEngine and RewriteRule
RewriteEngine On turns rewriting on for that scope (VirtualHost, Directory, or .htaccess). Each RewriteRule pattern substitution [flags] then matches the requested path against a regular expression and, if it matches, replaces it with the substitution. For example, RewriteRule ^products/([0-9]+)/?$ product.php?id=$1 [L] sends /products/42 internally to product.php?id=42.
RewriteCond: Rewriting Conditionally
RewriteCond adds a condition that must be true immediately before the RewriteRule below it applies -- checking things like the request's scheme, host, or whether a file already exists. A very common pattern forces HTTPS: RewriteCond %{HTTPS} off followed by a rule that redirects to the https:// version of the same URL.
Common Flags
Flags in [brackets] change how a rule behaves. [L] (last) stops processing further rules once this one matches. [R] or [R=301] issues an actual browser redirect instead of an internal rewrite, with the number setting the HTTP status code. [NC] makes the pattern case-insensitive. [QSA] appends the original query string to the rewritten URL instead of discarding it.
[L] lets Apache keep evaluating rules after a match, which can rewrite the URL a second time in a way you didn't intend -- almost every real-world rule set needs it.Example: Clean URLs and forcing HTTPS with mod_rewrite
RewriteEngine On
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# /products/42 -> product.php?id=42
RewriteRule ^products/([0-9]+)/?$ product.php?id=$1 [L,QSA]
{# Flagged by hand after confirming a runner can't handle this example
(a shell command / go.mod file stored as a TopicExample, a language
feature the configured runner version doesn't support, or output
that blows a runner's sandbox limit) -- see TopicExample.norun.
Never render the run button for these, regardless of language,
since it would just fail at execute_code (or worse, hang the
Judge0 queue on a submission that can never finish cleanly). #}
- Forgetting
RewriteEngine Onat the top of the scope -- every RewriteRule below it is silently ignored without it. - Leaving off the
[L]flag, letting a later rule further rewrite a URL that already matched, producing confusing double-rewritten results. - Writing rules directly in
.htaccesswhenAllowOverridedoesn't permitFileInfofor that directory, so the rules are parsed but never actually take effect.
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: