| <?xml version='1.0' encoding='UTF-8' ?> | |
| <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd"> | |
| <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?> | |
| <!-- $LastChangedRevision$ --> | |
| <!-- | |
| Licensed to the Apache Software Foundation (ASF) under one or more | |
| contributor license agreements. See the NOTICE file distributed with | |
| this work for additional information regarding copyright ownership. | |
| The ASF licenses this file to You under the Apache License, Version 2.0 | |
| (the "License"); you may not use this file except in compliance with | |
| the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| --> | |
| <manualpage metafile="intro.xml.meta"> | |
| <parentdocument href="./">Rewrite</parentdocument> | |
| <title>Apache mod_rewrite Introduction</title> | |
| <summary> | |
| <p>This document supplements the <module>mod_rewrite</module> | |
| <a href="../mod/mod_rewrite.html">reference documentation</a>. It | |
| describes the basic concepts necessary for use of | |
| <module>mod_rewrite</module>. Other documents go into greater detail, | |
| but this doc should help the beginner get their feet wet. | |
| </p> | |
| </summary> | |
| <seealso><a href="../mod/mod_rewrite.html">Module documentation</a></seealso> | |
| <seealso><a href="remapping.html">Redirection and remapping</a></seealso> | |
| <seealso><a href="htaccess.html">Per-directory Rewrites</a></seealso> | |
| <seealso><a href="flags.html">RewriteRule Flags</a></seealso> | |
| <seealso><a href="vhosts.html">Virtual hosts</a></seealso> | |
| <seealso><a href="rewritemap.html">Using RewriteMap</a></seealso> | |
| <seealso><a href="avoid.html">When not to use mod_rewrite</a></seealso> | |
| <seealso><a href="tech.html">Technical details</a></seealso> | |
| <section id="introduction"><title>Introduction</title> | |
| <p>The Apache module <module>mod_rewrite</module> is a very powerful and | |
| sophisticated module which provides a way to do URL manipulations. With | |
| it, you can do nearly all types of URL rewriting that you may need. It | |
| is, however, somewhat complex, and may be intimidating to the beginner. | |
| There is also a tendency to treat rewrite rules as magic incantation, | |
| using them without actually understanding what they do.</p> | |
| <p>This document attempts to give sufficient background so that what | |
| follows is understood, rather than just copied blindly. | |
| </p> | |
| <p>Remember that many common URL-manipulation tasks don't require the | |
| full power and complexity of <module>mod_rewrite</module>. For simple | |
| tasks, see <module>mod_alias</module> and the documentation | |
| on <a href="../urlmapping.html">mapping URLs to the | |
| filesystem</a>.</p> | |
| <p>Finally, before proceeding, be sure to configure | |
| <module>mod_rewrite</module>'s log level to one of the trace levels using | |
| the <directive module="core">LogLevel</directive> directive. Although this | |
| can give an overwhelming amount of information, it is indispensable in | |
| debugging problems with <module>mod_rewrite</module> configuration, since | |
| it will tell you exactly how each rule is processed.</p> | |
| <p class="figure"> | |
| <img src="../images/rewrite_simplified_overview.png" | |
| alt="Simplified flowchart of mod_rewrite processing: request | |
| arrives, check RewriteEngine On, iterate rules in order, | |
| test pattern match and RewriteCond, apply substitution if | |
| both pass, stop if L or END flag is set, otherwise continue | |
| to next rule" /><br /> | |
| <dfn>Figure:</dfn> Simplified overview of how | |
| <module>mod_rewrite</module> processes a request. See | |
| <a href="tech.html">Technical Details</a> for the full | |
| processing model including phases, flags, and looping. | |
| </p> | |
| </section> | |
| <section id="regex"><title>Regular Expressions</title> | |
| <p><module>mod_rewrite</module> uses the <a href="https://www.pcre.org/current/doc/html/pcre2syntax.html">Perl Compatible | |
| Regular Expressions</a> vocabulary, via the PCRE2 library. In this document, we do not attempt | |
| to provide a detailed reference to regular expressions. For that, we | |
| recommend the <a href="https://www.pcre.org/current/doc/html/pcre2syntax.html">PCRE2 documentation</a>, the | |
| <a href="https://perldoc.perl.org/perlre">Perl regular | |
| expressions man page</a>, and <a | |
| href="https://www.oreilly.com/library/view/mastering-regular-expressions/0596528124/">Mastering | |
| Regular Expressions, by Jeffrey Friedl</a> (the third edition is from | |
| 2006, but regular expression syntax is essentially unchanged, and this | |
| remains the definitive reference on the subject).</p> | |
| <p>In this document, we attempt to provide enough of a regex vocabulary | |
| to get you started, without being overwhelming, in the hope that | |
| <directive module="mod_rewrite">RewriteRule</directive>s will be scientific | |
| formulae, rather than magical incantations.</p> | |
| <section id="regexvocab"><title>Regex vocabulary</title> | |
| <p>The following are the minimal building blocks you will need, in order | |
| to write regular expressions and <directive | |
| module="mod_rewrite">RewriteRule</directive>s. They certainly do not | |
| represent a complete regular expression vocabulary, but they are a good | |
| place to start, and should help you read basic regular expressions, as | |
| well as write your own.</p> | |
| <table> | |
| <tr> | |
| <th>Character</th> | |
| <th>Meaning</th> | |
| <th>Example</th> | |
| </tr> | |
| <tr> | |
| <td><code>.</code></td> | |
| <td>Matches any single character</td> | |
| <td><code>c.t</code> will match <code>cat</code>, <code>cot</code>, | |
| <code>cut</code>, etc</td> | |
| </tr> | |
| <tr> | |
| <td><code>+</code></td> | |
| <td>Repeats the previous match one or more times</td> | |
| <td><code>a+</code> matches <code>a</code>, <code>aa</code>, | |
| <code>aaa</code>, etc</td> | |
| </tr> | |
| <tr> | |
| <td><code>*</code></td> | |
| <td>Repeats the previous match zero or more times</td> | |
| <td><code>a*</code> matches all the same things <code>a+</code> matches, | |
| but will also match an empty string</td> | |
| </tr> | |
| <tr> | |
| <td><code>?</code></td> | |
| <td>Makes the match optional</td> | |
| <td><code>colou?r</code> will match <code>color</code> and | |
| <code>colour</code></td> | |
| </tr> | |
| <tr> | |
| <td><code>\</code></td> | |
| <td>Escape the next character</td> | |
| <td><code>\.</code> will match <code>.</code> (dot) and not <em>any single | |
| character</em> as explain above</td> | |
| </tr> | |
| <tr> | |
| <td><code>^</code></td> | |
| <td>Called an anchor, matches the beginning of the string</td> | |
| <td><code>^a</code> matches a string that begins with <code>a</code></td> | |
| </tr> | |
| <tr> | |
| <td><code>$</code></td> | |
| <td>The other anchor, this matches the end of the string</td> | |
| <td><code>a$</code> matches a string that ends with <code>a</code></td> | |
| </tr> | |
| <tr> | |
| <td><code>( )</code></td> | |
| <td>Groups several characters into a single unit, and captures a match | |
| for use in a backreference</td> | |
| <td><code>(ab)+</code> matches <code>ababab</code> - that is, the | |
| <code>+</code> applies to the group. For more on backreferences see | |
| <a href="#InternalBackRefs">below</a></td> | |
| </tr> | |
| <tr> | |
| <td><code>[ ]</code></td> | |
| <td>A character class - matches one of the characters</td> | |
| <td><code>c[uoa]t</code> matches <code>cut</code>, <code>cot</code> or | |
| <code>cat</code></td> | |
| </tr> | |
| <tr> | |
| <td><code>[^ ]</code></td> | |
| <td>Negative character class - matches any character not specified</td> | |
| <td><code>c[^/]t</code> matches <code>cat</code> or <code>c=t</code> but | |
| not <code>c/t</code></td></tr> | |
| </table> | |
| <p>The <code>!</code> (Not) character can be | |
| used before a regular expression to negate it. This is, a string will | |
| be considered to have matched only if it does not match the rest of | |
| the expression.</p> | |
| <p>When using <code>!</code> to negate a pattern, note that | |
| <a href="#InternalBackRefs">backreferences</a> (e.g. | |
| <code>$1</code>, <code>$2</code>) are not available, since the | |
| pattern does not match.</p> | |
| <p>For example, the following will redirect any request that does | |
| <em>not</em> start with <code>/admin</code></p> | |
| <highlight language="config"> | |
| RewriteRule "!^/admin" "/xyz.html" [R,L] | |
| </highlight> | |
| </section> | |
| <section id="InternalBackRefs"><title>Regex Back-Reference Availability</title> | |
| <p>One important thing here has to be remembered: Whenever you | |
| use parentheses in <em>Pattern</em> or in one of the | |
| <em>CondPattern</em>, back-references are internally created | |
| which can be used with the strings <code>$N</code> and | |
| <code>%N</code> (see below). These are available for creating | |
| the <em>Substitution</em> parameter of a | |
| <directive module="mod_rewrite">RewriteRule</directive> or | |
| the <em>TestString</em> parameter of a | |
| <directive module="mod_rewrite">RewriteCond</directive>.</p> | |
| <p> Captures in the <directive module="mod_rewrite" | |
| >RewriteRule</directive> patterns are (counterintuitively) available to | |
| all preceding | |
| <directive module="mod_rewrite">RewriteCond</directive> directives, | |
| because the <directive module="mod_rewrite">RewriteRule</directive> | |
| expression is evaluated before the individual conditions.</p> | |
| <p>Figure 1 shows to which | |
| locations the back-references are transferred for expansion as | |
| well as illustrating the flow of the RewriteRule, RewriteCond | |
| matching. In the next chapters, we will be exploring how to use | |
| these back-references, so do not fret if it seems a bit alien | |
| to you at first. | |
| </p> | |
| <p class="figure"> | |
| <img src="../images/rewrite_backreferences.png" | |
| alt="Diagram showing how backreferences flow between | |
| RewriteRule and RewriteCond: $1-$9 capture groups from the | |
| RewriteRule pattern, %1-%9 capture groups from the most recent | |
| RewriteCond TestString pattern, both available in the | |
| substitution string and in subsequent RewriteCond TestStrings" /><br /> | |
| <dfn>Figure 1:</dfn> The back-reference flow through a rule.<br /> | |
| In this example, a request for <code>/test/1234</code> to host <code>admin.example.com</code> would be transformed into <code>/admin.foo?page=test&id=1234&host=admin.example.com</code>, provided that <code>%{DOCUMENT_ROOT}/test</code> is not an existing file. | |
| </p> | |
| <p>See also <a href="tech.html#InternalRuleset">Technical Details</a> | |
| for a diagram showing backreference flow with multiple conditions.</p> | |
| </section> | |
| </section> | |
| <section id="rewriterule"><title>RewriteRule Basics</title> | |
| <p>A <directive module="mod_rewrite">RewriteRule</directive> consists | |
| of three arguments separated by spaces. The arguments are</p> | |
| <ol> | |
| <li><var>Pattern</var>: which incoming URLs should be affected by the rule;</li> | |
| <li><var>Substitution</var>: where should the matching requests be sent;</li> | |
| <li><var>[flags]</var>: options affecting the rewritten request.</li> | |
| </ol> | |
| <p>The <var>Pattern</var> is a <a href="#regex">regular expression</a>. | |
| In server or virtualhost context, it is matched against the | |
| %-decoded <a href="../directive-dict.html#Syntax">URL-path</a> | |
| of the incoming request — the part after the hostname and port, | |
| and not including the query string (e.g., <code>/app/index.html</code>). | |
| In <glossary ref="perdirectory">per-directory context</glossary>, | |
| the pattern is matched against the request's path relative to the | |
| directory for which the rule is defined (with the directory prefix | |
| stripped — see <a href="htaccess.html#path-stripping">Per-directory | |
| Rewrites</a> for details). | |
| </p> | |
| <p>Once a substitution has occurred, any rules that follow are | |
| matched against the substituted value.</p> | |
| <p>The <var>Pattern</var> is matched only against the URL-path | |
| — not the hostname, port, or query string. To match against | |
| those, use a | |
| <directive module="mod_rewrite">RewriteCond</directive> with the | |
| <code>%{HTTP_HOST}</code>, <code>%{SERVER_PORT}</code>, or | |
| <code>%{QUERY_STRING}</code> variables respectively.</p> | |
| <note><module>mod_rewrite</module> operates entirely on the URL-path | |
| and HTTP headers. It cannot inspect the request body (e.g., POST | |
| data). If you need to make routing decisions based on request body | |
| content, handle that in your application logic or use a module such | |
| as <module>mod_request</module> paired with a custom filter.</note> | |
| <p class="figure"> | |
| <img src="../images/syntax_rewriterule.png" | |
| alt="Annotated syntax diagram of the RewriteRule directive | |
| showing three components: Pattern (regex matched against the | |
| URL-path), Substitution (the replacement URL or path), and | |
| optional Flags in square brackets" /><br /> | |
| <dfn>Figure 2:</dfn> Syntax of the RewriteRule directive. | |
| </p> | |
| <p>The <var>Substitution</var> can itself be one of three things:</p> | |
| <dl> | |
| <dt>1. A full filesystem path to a resource</dt> | |
| <dd> | |
| <highlight language="config"> | |
| RewriteRule "^/games" "/usr/local/games/web/puzzles.html" | |
| </highlight> | |
| <p>This maps a request to an arbitrary location on your filesystem, much | |
| like the <directive module="mod_alias">Alias</directive> directive.</p> | |
| </dd> | |
| <dt>2. A web-path to a resource</dt> | |
| <dd> | |
| <highlight language="config"> | |
| RewriteRule "^/games$" "/puzzles.html" | |
| </highlight> | |
| <p>If <directive module="core">DocumentRoot</directive> is set | |
| to <code>/usr/local/apache2/htdocs</code>, then this directive would | |
| map requests for <code>http://example.com/games</code> to the | |
| path <code>/usr/local/apache2/htdocs/puzzles.html</code>.</p> | |
| </dd> | |
| <dt>3. An absolute URL</dt> | |
| <dd> | |
| <highlight language="config"> | |
| RewriteRule "^/product/view$" "http://site2.example.com/seeproduct.html" [R] | |
| </highlight> | |
| <p>This tells the client to make a new request for the specified URL.</p> | |
| </dd> | |
| </dl> | |
| <note type="warning">Note that <strong>1</strong> and <strong>2</strong> have exactly the same syntax. The difference between them is that in the case of <strong>1</strong>, the top level of the target path (i.e., <code>/usr/</code>) exists on the filesystem, where as in the case of <strong>2</strong>, it does not. (i.e., there's no <code>/bar/</code> as a root-level directory in the filesystem.)</note> | |
| <p>The <var>Substitution</var> can also | |
| contain <em>back-references</em> to parts of the incoming URL-path | |
| matched by the <var>Pattern</var>. Consider the following:</p> | |
| <highlight language="config"> | |
| RewriteRule "^/product/(.*)/view$" "/var/web/productdb/$1" | |
| </highlight> | |
| <p>The variable <code>$1</code> will be replaced with whatever text | |
| was matched by the expression inside the parenthesis in | |
| the <var>Pattern</var>. For example, a request | |
| for <code>http://example.com/product/r14df/view</code> will be mapped | |
| to the path <code>/var/web/productdb/r14df</code>.</p> | |
| <p>If there is more than one expression in parenthesis, they are | |
| available in order in the | |
| variables <code>$1</code>, <code>$2</code>, <code>$3</code>, and so | |
| on.</p> | |
| </section> | |
| <section id="flags"><title>Rewrite Flags</title> | |
| <p>The behavior of a <directive | |
| module="mod_rewrite">RewriteRule</directive> can be modified by the | |
| application of one or more flags to the end of the rule. For example, the | |
| matching behavior of a rule can be made case-insensitive by the | |
| application of the <code>[NC]</code> flag: | |
| </p> | |
| <highlight language="config"> | |
| RewriteRule "^puppy.html" "smalldog.html" [NC] | |
| </highlight> | |
| <p>For more details on the available flags, their meanings, and | |
| examples, see the <a href="flags.html">Rewrite Flags</a> document.</p> | |
| </section> | |
| <section id="rewritecond"><title>Rewrite Conditions</title> | |
| <p>One or more <directive module="mod_rewrite">RewriteCond</directive> | |
| directives can be used to restrict the types of requests that will be | |
| subject to the | |
| following <directive module="mod_rewrite">RewriteRule</directive>. The | |
| first argument is a variable describing a characteristic of the | |
| request, the second argument is a <a href="#regex">regular | |
| expression</a> that must match the variable, and a third optional | |
| argument is a list of flags that modify how the match is evaluated.</p> | |
| <p class="figure"> | |
| <img src="../images/syntax_rewritecond.png" | |
| alt="Annotated syntax diagram of the RewriteCond directive | |
| showing two components: TestString (variable or text to test) | |
| and CondPattern (regex or comparison to evaluate), with optional | |
| flags in square brackets" /><br /> | |
| <dfn>Figure 3:</dfn> Syntax of the RewriteCond directive | |
| </p> | |
| <p>For example, to send all requests from a particular IP range to a | |
| different server, you could use:</p> | |
| <highlight language="config"> | |
| RewriteCond "%{REMOTE_ADDR}" "^10\.2\." | |
| RewriteRule "(.*)" "http://intranet.example.com$1" | |
| </highlight> | |
| <p>When more than | |
| one <directive module="mod_rewrite">RewriteCond</directive> is | |
| specified, they must all match for | |
| the <directive module="mod_rewrite">RewriteRule</directive> to be | |
| applied. For example, to deny requests that contain the word "hack" in | |
| their query string, unless they also contain a cookie containing | |
| the word "go", you could use:</p> | |
| <highlight language="config"> | |
| RewriteCond "%{QUERY_STRING}" "hack" | |
| RewriteCond "%{HTTP_COOKIE}" !go | |
| RewriteRule "." "-" [F] | |
| </highlight> | |
| <p>Notice that the exclamation mark specifies a negative match, so the rule is only applied if the cookie does not contain "go".</p> | |
| <p>Matches in the regular expressions contained in | |
| the <directive module="mod_rewrite">RewriteCond</directive>s can be | |
| used as part of the <var>Substitution</var> in | |
| the <directive module="mod_rewrite">RewriteRule</directive> using the | |
| variables <code>%1</code>, <code>%2</code>, etc. For example, this | |
| will direct the request to a different directory depending on the | |
| hostname used to access the site:</p> | |
| <highlight language="config"> | |
| RewriteCond "%{HTTP_HOST}" "(.*)" | |
| RewriteRule "^/(.*)" "/sites/%1/$1" | |
| </highlight> | |
| <p>If the request was for <code>http://example.com/foo/bar</code>, | |
| then <code>%1</code> would contain <code>example.com</code> | |
| and <code>$1</code> would contain <code>foo/bar</code>.</p> | |
| </section> | |
| <section id="rewritemap"><title>Rewrite maps</title> | |
| <p>The <directive module="mod_rewrite">RewriteMap</directive> directive | |
| provides a way to call an external function, so to speak, to do your | |
| rewriting for you. This is discussed in greater detail in the <a | |
| href="rewritemap.html">RewriteMap supplementary documentation</a>.</p> | |
| </section> | |
| <section id="htaccess"><title>.htaccess files</title> | |
| <p>It is possible to use rewrite rules in | |
| <glossary ref="perdirectory">per-directory</glossary> context | |
| (<a href="../howto/htaccess.html"><code>.htaccess</code> files</a> and | |
| <directive type="section" module="core">Directory</directive> blocks), | |
| but the rules behave differently there — in particular, the directory | |
| prefix is stripped from the URL before matching. See the | |
| <a href="htaccess.html#path-stripping">Per-directory Rewrites</a> | |
| document for full details. Note that | |
| <directive module="core" type="section">If</directive> and | |
| <directive module="core" type="section">Location</directive> blocks | |
| also trigger per-directory behavior — see | |
| <a href="htaccess.html#context-restrictions">Which contexts support rewrite rules?</a>.</p> | |
| </section> | |
| <section id="security"><title>Security Considerations</title> | |
| <p><module>mod_rewrite</module> is a powerful URL manipulation tool, and | |
| with that power comes the potential for security mistakes. This section | |
| highlights the most common security pitfalls to watch for when writing | |
| rewrite rules.</p> | |
| <section id="security-redirect"><title>Open Redirects</title> | |
| <p>If a <directive module="mod_rewrite">RewriteRule</directive> | |
| constructs a redirect URL using unvalidated user input, an attacker | |
| can craft a link that redirects visitors to a malicious site while | |
| appearing to originate from your domain. This is known as an | |
| <em>open redirect</em> vulnerability.</p> | |
| <p>For example, this rule is dangerous:</p> | |
| <highlight language="config"> | |
| # DANGEROUS - allows open redirect | |
| RewriteRule "^/redirect" "%{QUERY_STRING}" [R,L] | |
| </highlight> | |
| <p>An attacker could use | |
| <code>https://yoursite.com/redirect?https://evil.com</code> to redirect | |
| users to a malicious site. Always validate or constrain redirect | |
| targets. If the destination must be on your own site, ensure the | |
| substitution begins with <code>/</code> (a relative path) rather than | |
| allowing a full URL from user input.</p> | |
| </section> | |
| <section id="security-ssrf"><title>Server-Side Request Forgery (SSRF)</title> | |
| <p>When using the <a href="flags.html#flag_p">[P] (proxy) flag</a>, | |
| <module>mod_rewrite</module> causes the server to make an HTTP request | |
| to the substitution URL on behalf of the client. If any part of that | |
| URL is derived from user input - backreferences, query strings, or | |
| headers - an attacker may be able to cause your server to make requests | |
| to arbitrary internal services or external hosts.</p> | |
| <p>For example:</p> | |
| <highlight language="config"> | |
| # DANGEROUS - user controls the proxy target | |
| RewriteCond "%{QUERY_STRING}" "target=(.+)" | |
| RewriteRule "^/fetch" "http://%1" [P] | |
| </highlight> | |
| <p>An attacker could use this to probe internal network services that | |
| are not otherwise accessible from the internet. Always use a fixed | |
| hostname in proxy targets, and limit backreferences to the path | |
| component only.</p> | |
| </section> | |
| <section id="security-path"><title>Path Traversal</title> | |
| <p>Rewrite rules that map user-supplied path components directly to | |
| the filesystem can allow path traversal attacks if the input is not | |
| properly constrained. For example:</p> | |
| <highlight language="config"> | |
| # DANGEROUS - allows path traversal | |
| RewriteRule "^/files/(.+)" "/var/data/$1" [L] | |
| </highlight> | |
| <p>A request for <code>/files/../../etc/passwd</code> could potentially | |
| access files outside the intended directory. Use restrictive patterns | |
| in your <directive module="mod_rewrite">RewriteRule</directive> (for | |
| example, <code>[a-zA-Z0-9_-]+</code> instead of <code>.+</code>), and | |
| rely on Apache's built-in protections | |
| (<directive module="core">Options</directive> and | |
| <directive module="core" type="section">Directory</directive> | |
| restrictions) as defense in depth.</p> | |
| </section> | |
| </section> | |
| </manualpage> |