RewritecondEdit
Rewritecond
Rewritecond is a directive used in the Apache HTTP Server’s mod_rewrite subsystem to introduce conditional logic into URL rewriting. It allows administrators to specify test strings and patterns that must be satisfied for the subsequent RewriteRule to apply. This mechanism makes it possible to route requests differently based on factors such as the request path, host, protocol, or environment variables, without duplicating rules or hard-coding every possibility.
In practice, Rewritecond blocks are paired with a following RewriteRule. Each block begins with one or more RewriteCond lines that define tests, followed by a RewriteRule that is executed only if all the preceding conditions pass. This structure enables concise and flexible configuration, especially on sites that need to support multiple languages, schemes, or legacy paths.
Overview
- Purpose and scope: Rewritecond is used to gate a rewriting decision on specific per-request conditions. It operates within the larger framework of mod_rewrite and relies on test strings and patterns evaluated against the current request.
- Interaction with RewriteRule: A RewriteRule is only considered if its associated RewriteCond lines succeed. If there are multiple RewriteCond blocks, all must pass (unless an OR flag is used to connect to the next condition).
- Environment and test strings: TestString can reference server variables such as %{REQUEST_URI}, %{QUERY_STRING}, %{HTTP_HOST}, %{HTTPS}, %{REMOTE_ADDR}, and many others. These are often combined with CondPattern that uses Perl Compatible Regular Expressions (PCRE) to determine a match.
- Pattern matching: CondPattern is typically a PCRE pattern. A common practice is to negate a condition by prefixing the pattern with a minus sign or by using a negation form within the pattern itself.
- Flags: Each RewriteCond may carry flags that modify its behavior. The most common flag is NC (no case) to make the match case-insensitive, and OR to connect this condition to the next condition in an either/or fashion.
Syntax and semantics
- Basic form: RewriteCond TestString CondPattern [Flags]
- TestString: A string to test, often a server variable in the form %{VAR} or a literal string. Examples include %{REQUEST_URI}, %{HTTPS}, %{QUERY_STRING}, and %{REMOTE_ADDR}.
- CondPattern: A PCRE expression or a literal string used to determine a match against TestString.
- Negation and matching: Negation can be achieved by including a leading exclamation mark in the CondPattern (e.g., %{REQUEST_FILENAME} !-f to test that the request does not map to an existing file). The pattern can be anchored or using wildcards as appropriate for PCRE.
- Flags: In addition to NC and OR, there are other pattern-related flags that can affect the matching behavior. The exact set of flags is documented in the mod_rewrite reference, but the most frequently used are NC for case-insensitive matching and OR for combining conditions in an either/or manner.
- Scope: Conditions are evaluated in the order they appear, and their results influence the subsequent RewriteRule within the same rewrite block or context.
Typical usage patterns
- Simple existence checks:
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule ^(.+)$ index.php [L] This pattern routes requests that are not for real files or directories to a front controller script, a common approach in modern web frameworks.
- Protocol or host-based decisions:
- RewriteCond %{HTTPS} off
- RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] This ensures secure connections without duplicating content across schemes.
- Path-based routing with OR:
- RewriteCond %{REQUEST_URI} ^/shop/ [OR]
- RewriteCond %{REQUEST_URI} ^/store/
- RewriteRule ^(.*)$ /shop/index.php [L] This allows several related paths to be handled by a single script.
- Language or locale negotiation:
- RewriteCond %{HTTP:Accept-Language} (en|fr|es) [NC]
- RewriteRule ^$ /%1/index.html [L] Language-aware routing can be implemented by matching the client’s preferred language and directing to the appropriate content.
Examples
- Redirect non-existent paths to a front controller:
- RewriteEngine On
- RewriteCond %{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_FILENAME} !-d
- RewriteRule ^(.+)$ index.php [L] This keeps static assets working while sending all other requests through a central script.
- Enforce secure access for a specific path:
- RewriteCond %{HTTPS} !=on
- RewriteCond %{REQUEST_URI} ^/secure/
- RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
- Preserve clean URLs while testing for a legacy path:
- RewriteCond %{REQUEST_URI} ^/legacy/(.*)$ [NC]
- RewriteRule ^legacy/(.*)$ legacy/index.php?$1 [L,QSA]
Performance and maintenance
- Early exits: Position RewriteCond lines before the associated RewriteRule to fail fast when conditions are not met, reducing unnecessary rule processing.
- Minimize complexity: Use straightforward test strings and patterns when possible. Complex PCRE patterns can complicate maintenance and slow down request handling.
- Compatibility: When configuring per-directory rules in .htaccess files, remember that the context and performance characteristics differ from server-wide configurations. In some cases, consolidating rules in a central configuration can improve performance.
Debugging and troubleshooting
- Logging: Modern Apache versions provide ways to increase rewrite logging verbosity without enabling legacy rewrite logs. This helps diagnose which conditions are passing or failing for a given request.
- Incremental testing: Test RewriteCond blocks with concrete URLs and known inputs to verify that the intended RewriteRule behavior is achieved, and adjust patterns and flags as needed.
- Common pitfalls: Misplaced OR flags or miscounted condition blocks can lead to unexpected rewrites or no rewrites at all. Ensuring that conditions follow the intended logical structure is essential.