← Back to Apache Course | Chapter 7: Advanced | Lesson 3 of 4

URL Rewriting

This lesson zooms out from mod_rewrite's syntax to the practical patterns URL rewriting is actually used for in real sites -- clean URLs, redirects after a site restructure, and enforcing canonical addresses.

Clean URLs for a Framework Front Controller

Most modern frameworks (Laravel, Symfony, Django when served through a proxy) route every request through a single entry file. A rewrite rule sends any request that doesn't match a real file or directory to that entry point instead: checking %{REQUEST_FILENAME} isn't an existing file or directory with RewriteCond, then rewriting everything else to index.php (or the equivalent) so the framework's own router takes over from there.

Redirecting an Old Site Structure

After a site redesign, old URLs often need to keep working -- an SEO and user-experience necessity, not an optional nicety. Individual Redirect directives handle a handful of one-off moved pages; a RewriteRule with capture groups handles a whole pattern at once, e.g. mapping every old /articles/123 URL to a new /blog/123-post-title scheme via a lookup, or a simpler pattern-based transformation.

Enforcing One Canonical URL

Search engines treat example.com, www.example.com, and even the same page reachable over both HTTP and HTTPS as separate, competing URLs unless you tell them otherwise. A RewriteCond/RewriteRule pair that redirects any non-www request to www. (or vice versa -- pick one and stay consistent) is standard practice, alongside the HTTPS-forcing rule from the mod_rewrite lesson.

Rewrite vs. Redirect

It's worth being deliberate about which one a rule actually needs: an internal rewrite (no [R] flag) changes what Apache serves without the browser's address bar changing at all -- right for a clean-URL front controller. A redirect ([R=301] or [R=302]) sends the browser an actual new address to go to -- right for telling both users and search engines that a URL has permanently moved.

Note: 301 (permanent) tells browsers and search engines to update their records and stop asking for the old URL; 302 (temporary) doesn't -- use 301 for a genuinely permanent move, 302 for anything short-term or reversible.

Example: A framework front-controller rewrite plus canonical www redirect

apacheconf
RewriteEngine On

# Force www.
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

# Front controller: send anything that isn't a real file/dir to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
{# 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). #}

⚠️ This example can't run in the browser editor. Try it in your own local environment instead.

{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using an internal rewrite when a real redirect was needed (or the reverse), leaving the browser's address bar showing the wrong URL, or search engines never learning a page moved.
  2. Using a 302 for a permanent move, so search engines keep the old URL indexed instead of transferring its ranking to the new one.
  3. Writing a front-controller rewrite that also intercepts requests for real files (like images or CSS), which then get routed to the application instead of served directly.
🔒

Chapter Quiz — Complete all 4 topics to unlock

0/4 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.