From: Rich Bowen Date: Sat, 2 May 2026 19:18:57 +0000 (+0000) Subject: rewrite guide: add modern recipes - HTTPS enforcement, trailing slash, www canonicali... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b547b0373391a14cdd00a916e30a795a96671241;p=thirdparty%2Fapache%2Fhttpd.git rewrite guide: add modern recipes - HTTPS enforcement, trailing slash, www canonicalization, front-controller routing (BZ 58892, step 8) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1933707 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/docs/manual/rewrite/remapping.xml b/docs/manual/rewrite/remapping.xml index 8b03fcb322..200d0737fe 100644 --- a/docs/manual/rewrite/remapping.xml +++ b/docs/manual/rewrite/remapping.xml @@ -80,6 +80,230 @@ RewriteRule "^/foo\.html$" "/bar.html" [PT +
+ + Forcing HTTPS + +
+
Description:
+ +
+

You want all HTTP requests to be redirected to HTTPS. This + is one of the most common uses of mod_rewrite, + but in most cases it is better accomplished without it.

+
+ +
Solution:
+ +
+ +

The preferred approach uses a + Redirect directive in a + dedicated HTTP virtual host:

+ + +<VirtualHost *:80> + ServerName www.example.com + Redirect permanent "/" "https://www.example.com/" +</VirtualHost> + +<VirtualHost *:443> + ServerName www.example.com + # ... SSL configuration goes here +</VirtualHost> + + +
+ +
Discussion:
+ +
+

If you do not have access to the main server configuration and + must use a .htaccess file, mod_rewrite + is the appropriate tool:

+ + +RewriteEngine On +RewriteCond "%{HTTPS}" !=on +RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L] + + +

The %{HTTPS} variable is set to on + when the connection is using SSL/TLS, and is empty or + off otherwise. Using R=301 issues a + permanent redirect, which tells search engines to update their + index.

+ +

See also the When not to use + mod_rewrite document for more discussion of the + Redirect approach.

+
+
+ +
+ +
+ + Trailing Slash Normalization + +
+
Description:
+ +
+

You want to ensure that URLs for directories always end with + a trailing slash, or conversely, that they never do. This is a + common requirement for SEO and for consistent URL handling by + web applications.

+
+ +
Solution:
+ +
+

To add a trailing slash to URLs that map to directories:

+ + +RewriteCond "%{REQUEST_FILENAME}" -d +RewriteCond "%{REQUEST_URI}" "!/$" +RewriteRule "^(.*)$" "$1/" [R=301,L] + + +

To remove a trailing slash (except for actual directories):

+ + +RewriteCond "%{REQUEST_FILENAME}" !-d +RewriteCond "%{REQUEST_URI}" "(.+)/$" +RewriteRule "^" "%1" [R=301,L] + + +
+ +
Discussion:
+ +
+

Apache's mod_dir already handles trailing + slash redirects for real directories when + DirectorySlash is enabled + (the default). You only need a mod_rewrite rule + if you want to enforce trailing slash behavior for URLs that do + not correspond to actual directories on disk, or if you want to + remove trailing slashes.

+
+
+ +
+ +
+ + Canonical www/non-www Hostname + +
+
Description:
+ +
+

You want to force all requests to use either + www.example.com or example.com, + not both. This ensures search engines treat them as one site + and prevents cookie scope issues.

+
+ +
Solution:
+ +
+

The best approach does not use mod_rewrite at + all. Place a Redirect + in the virtual host for the non-canonical hostname:

+ + +# Redirect example.com -> www.example.com +<VirtualHost *:80 *:443> + ServerName example.com + Redirect permanent "/" "https://www.example.com/" +</VirtualHost> + + +

If you only have .htaccess access:

+ + +# Add www +RewriteEngine On +RewriteCond "%{HTTP_HOST}" "!^www\." [NC] +RewriteRule "^(.*)" "https://www.%{HTTP_HOST}$1" [R=301,L] + + + +# Remove www +RewriteEngine On +RewriteCond "%{HTTP_HOST}" "^www\.(.+)$" [NC] +RewriteRule "^(.*)" "https://%1$1" [R=301,L] + + +
+ +
Discussion:
+ +
+

See also the Canonical Hostnames + recipe above, which covers the general case. This recipe focuses + specifically on the www/non-www choice, which is the most common + hostname canonicalization need.

+
+
+ +
+ +
+ + Front Controller / Application Routing + +
+
Description:
+ +
+

Most modern web frameworks (PHP, Python, Ruby, etc.) use a + single entry point - often called a "front controller" - that + handles all requests. URLs like /products/widget + are routed to index.php (or equivalent), which + parses the URL internally.

+
+ +
Solution:
+ +
+ + For this use case, the + FallbackResource directive is + almost always the better choice. See the + Fallback Resource recipe above. + +

If you need mod_rewrite (for example, to add + additional conditions), the standard pattern is:

+ + +RewriteEngine On +RewriteCond "%{REQUEST_FILENAME}" !-f +RewriteCond "%{REQUEST_FILENAME}" !-d +RewriteRule "^(.*)$" "/index.php" [L] + + +

The !-f and !-d conditions skip the + rule for requests that map to an existing file or directory, so + static assets (images, CSS, JavaScript) are still served + directly.

+
+ +
Discussion:
+ +
+

In .htaccess context, consider using + [END] instead of [L] to avoid + reprocessing loops. See the + .htaccess looping discussion + for details.

+
+
+ +
+
Rewriting From Old to New (external)