Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 771 | blopes | 1 | <!DOCTYPE html SYSTEM "about:legacy-compat"> |
| 2 | <html lang="en"><head><META http-equiv="Content-Type" content="text/html; charset=UTF-8"><link href="./images/docs-stylesheet.css" rel="stylesheet" type="text/css"><title>Apache Tomcat 9 (9.0.112) - The rewrite Valve</title></head><body><div id="wrapper"><header><div id="header"><div><div><div class="logo noPrint"><a href="https://tomcat.apache.org/"><img alt="Tomcat Home" src="./images/tomcat.png"></a></div><div style="height: 1px;"></div><div class="asfLogo noPrint"><a href="https://www.apache.org/" target="_blank"><img src="./images/asf-logo.svg" alt="The Apache Software Foundation" style="width: 266px; height: 83px;"></a></div><h1>Apache Tomcat 9</h1><div class="versionInfo"> |
||
| 3 | Version 9.0.112, |
||
| 4 | <time datetime="2025-11-06">Nov 6 2025</time></div><div style="height: 1px;"></div><div style="clear: left;"></div></div></div></div></header><div id="middle"><div><div id="mainLeft" class="noprint"><div><nav><div><h2>Links</h2><ul><li><a href="index.html">Docs Home</a></li><li><a href="https://cwiki.apache.org/confluence/display/TOMCAT/FAQ">FAQ</a></li></ul></div><div><h2>User Guide</h2><ul><li><a href="introduction.html">1) Introduction</a></li><li><a href="setup.html">2) Setup</a></li><li><a href="appdev/index.html">3) First webapp</a></li><li><a href="deployer-howto.html">4) Deployer</a></li><li><a href="manager-howto.html">5) Manager</a></li><li><a href="host-manager-howto.html">6) Host Manager</a></li><li><a href="realm-howto.html">7) Realms and AAA</a></li><li><a href="security-manager-howto.html">8) Security Manager</a></li><li><a href="jndi-resources-howto.html">9) JNDI Resources</a></li><li><a href="jndi-datasource-examples-howto.html">10) JDBC DataSources</a></li><li><a href="class-loader-howto.html">11) Classloading</a></li><li><a href="jasper-howto.html">12) JSPs</a></li><li><a href="ssl-howto.html">13) SSL/TLS</a></li><li><a href="ssi-howto.html">14) SSI</a></li><li><a href="cgi-howto.html">15) CGI</a></li><li><a href="proxy-howto.html">16) Proxy Support</a></li><li><a href="mbeans-descriptors-howto.html">17) MBeans Descriptors</a></li><li><a href="default-servlet.html">18) Default Servlet</a></li><li><a href="cluster-howto.html">19) Clustering</a></li><li><a href="balancer-howto.html">20) Load Balancer</a></li><li><a href="connectors.html">21) Connectors</a></li><li><a href="monitoring.html">22) Monitoring and Management</a></li><li><a href="logging.html">23) Logging</a></li><li><a href="apr.html">24) APR/Native</a></li><li><a href="virtual-hosting-howto.html">25) Virtual Hosting</a></li><li><a href="aio.html">26) Advanced IO</a></li><li><a href="maven-jars.html">27) Mavenized</a></li><li><a href="security-howto.html">28) Security Considerations</a></li><li><a href="windows-service-howto.html">29) Windows Service</a></li><li><a href="windows-auth-howto.html">30) Windows Authentication</a></li><li><a href="jdbc-pool.html">31) Tomcat's JDBC Pool</a></li><li><a href="web-socket-howto.html">32) WebSocket</a></li><li><a href="rewrite.html">33) Rewrite</a></li><li><a href="cdi.html">34) CDI 2 and JAX-RS</a></li><li><a href="graal.html">35) AOT/GraalVM Support</a></li></ul></div><div><h2>Reference</h2><ul><li><a href="RELEASE-NOTES.txt">Release Notes</a></li><li><a href="config/index.html">Configuration</a></li><li><a href="api/index.html">Tomcat Javadocs</a></li><li><a href="servletapi/index.html">Servlet 4.0 Javadocs</a></li><li><a href="jspapi/index.html">JSP 2.3 Javadocs</a></li><li><a href="elapi/index.html">EL 3.0 Javadocs</a></li><li><a href="websocketapi/index.html">WebSocket 1.1 Javadocs</a></li><li><a href="jaspicapi/index.html">JASPIC 1.1 Javadocs</a></li><li><a href="annotationapi/index.html">Common Annotations 1.3 Javadocs</a></li><li><a href="https://tomcat.apache.org/connectors-doc/">JK 1.2 Documentation</a></li></ul></div><div><h2>Apache Tomcat Development</h2><ul><li><a href="building.html">Building</a></li><li><a href="changelog.html">Changelog</a></li><li><a href="https://cwiki.apache.org/confluence/display/TOMCAT/Tomcat+Versions">Status</a></li><li><a href="developers.html">Developers</a></li><li><a href="architecture/index.html">Architecture</a></li><li><a href="tribes/introduction.html">Tribes</a></li></ul></div></nav></div></div><div id="mainRight"><div id="content"><h2>The rewrite Valve</h2><h3 id="Introduction">Introduction</h3><div class="text"> |
||
| 5 | |||
| 6 | <p>The rewrite valve implements URL rewrite functionality in a way that is |
||
| 7 | very similar to mod_rewrite from Apache HTTP Server.</p> |
||
| 8 | |||
| 9 | </div><h3 id="Configuration">Configuration</h3><div class="text"> |
||
| 10 | |||
| 11 | <p>The rewrite valve is configured as a valve using the <code>org.apache.catalina.valves.rewrite.RewriteValve</code> |
||
| 12 | class name.</p> |
||
| 13 | |||
| 14 | <p>The rewrite valve can be configured as a valve added in a Host. |
||
| 15 | See <a href="config/host.html">virtual-server</a> documentation for |
||
| 16 | information on how to configure it. It will use a <code>rewrite.config</code> file |
||
| 17 | containing the rewrite directives, it must be placed in the Host configuration |
||
| 18 | folder. |
||
| 19 | </p> |
||
| 20 | |||
| 21 | <p>It can also be in the context.xml of a webapp. |
||
| 22 | The valve will then use a <code>rewrite.config</code> file containing the |
||
| 23 | rewrite directives, it must be placed in the WEB-INF folder of the web application |
||
| 24 | </p> |
||
| 25 | |||
| 26 | </div><h3 id="Using_rewrite_rules_with_special_characters">Using rewrite rules with special characters</h3><div class="text"> |
||
| 27 | |||
| 28 | <p>The URL presented to the rewrite valve is the same URL used for request |
||
| 29 | mapping with any literal <code>'%'</code>, <code>';'</code> and/or |
||
| 30 | <code>'?'</code> characters encoded in <code>%nn</code> form.</p> |
||
| 31 | |||
| 32 | <p>A rewrite rule that wishes to insert a literal <code>'%'</code>, |
||
| 33 | <code>';'</code>, <code>'?'</code>, <code>'&'</code> or <code>'='</code> |
||
| 34 | character should do so in <code>%nn</code> form. Other characters maybe |
||
| 35 | inserted in either literal or <code>%nn</code> form.</p> |
||
| 36 | |||
| 37 | <p>This enables the rewrite rules to: |
||
| 38 | <ul> |
||
| 39 | <li>process URLs containing literal <code>'?'</code> characters;</li> |
||
| 40 | <li>add a query string;</li> |
||
| 41 | <li>insert a literal <code>'%'</code> character without it being confused with |
||
| 42 | <code>%nn</code> encoding.</li> |
||
| 43 | </ul> |
||
| 44 | </p> |
||
| 45 | |||
| 46 | </div><h3 id="Directives">Directives</h3><div class="text"> |
||
| 47 | |||
| 48 | <p>The rewrite.config file contains a list of directives which closely |
||
| 49 | resemble the directives used by mod_rewrite, in particular the central |
||
| 50 | RewriteRule and RewriteCond directives. Lines that start with a |
||
| 51 | <code>#</code> character are treated as comments and will be ignored.</p> |
||
| 52 | |||
| 53 | <p>Note: This section is a modified version of the mod_rewrite documentation, |
||
| 54 | which is Copyright 1995-2006 The Apache Software Foundation, and licensed under the |
||
| 55 | under the Apache License, Version 2.0.</p> |
||
| 56 | |||
| 57 | <div class="subsection"><h4 id="RewriteCond">RewriteCond</h4><div class="text"> |
||
| 58 | |||
| 59 | <p>Syntax: <code>RewriteCond TestString CondPattern</code></p> |
||
| 60 | |||
| 61 | <p>The RewriteCond directive defines a rule condition. One or more RewriteCond |
||
| 62 | can precede a RewriteRule directive. The following rule is then only used if both |
||
| 63 | the current state of the URI matches its pattern, and if these conditions are met.</p> |
||
| 64 | |||
| 65 | <p><em>TestString</em> is a string which can contain the |
||
| 66 | following expanded constructs in addition to plain text:</p> |
||
| 67 | |||
| 68 | <ul> |
||
| 69 | <li> |
||
| 70 | <strong>RewriteRule backreferences</strong>: These are |
||
| 71 | backreferences of the form <strong><code>$N</code></strong> |
||
| 72 | (0 <= N <= 9), which provide access to the grouped |
||
| 73 | parts (in parentheses) of the pattern, from the |
||
| 74 | <code>RewriteRule</code> which is subject to the current |
||
| 75 | set of <code>RewriteCond</code> conditions.. |
||
| 76 | </li> |
||
| 77 | <li> |
||
| 78 | <strong>RewriteCond backreferences</strong>: These are |
||
| 79 | backreferences of the form <strong><code>%N</code></strong> |
||
| 80 | (1 <= N <= 9), which provide access to the grouped |
||
| 81 | parts (again, in parentheses) of the pattern, from the last matched |
||
| 82 | <code>RewriteCond</code> in the current set |
||
| 83 | of conditions. |
||
| 84 | </li> |
||
| 85 | <li> |
||
| 86 | <strong>RewriteMap expansions</strong>: These are |
||
| 87 | expansions of the form <strong><code>${mapname:key|default}</code></strong>. |
||
| 88 | See <a href="#RewriteMap">the documentation for |
||
| 89 | RewriteMap</a> for more details. |
||
| 90 | </li> |
||
| 91 | <li> |
||
| 92 | <strong>Server-Variables</strong>: These are variables of |
||
| 93 | the form |
||
| 94 | <strong><code>%{</code> <em>NAME_OF_VARIABLE</em> |
||
| 95 | <code>}</code></strong> |
||
| 96 | where <em>NAME_OF_VARIABLE</em> can be a string taken |
||
| 97 | from the following list: |
||
| 98 | |||
| 99 | <ul> |
||
| 100 | <li> |
||
| 101 | <p><b>HTTP headers:</b></p> |
||
| 102 | <p> |
||
| 103 | HTTP_USER_AGENT<br> |
||
| 104 | HTTP_REFERER<br> |
||
| 105 | HTTP_COOKIE<br> |
||
| 106 | HTTP_FORWARDED<br> |
||
| 107 | HTTP_HOST<br> |
||
| 108 | HTTP_PROXY_CONNECTION<br> |
||
| 109 | HTTP_ACCEPT<br> |
||
| 110 | </p> |
||
| 111 | </li> |
||
| 112 | <li> |
||
| 113 | <p><b>connection & request:</b></p> |
||
| 114 | <p> |
||
| 115 | REMOTE_ADDR<br> |
||
| 116 | REMOTE_HOST<br> |
||
| 117 | REMOTE_PORT<br> |
||
| 118 | REMOTE_USER<br> |
||
| 119 | REMOTE_IDENT<br> |
||
| 120 | REQUEST_METHOD<br> |
||
| 121 | SCRIPT_FILENAME<br> |
||
| 122 | REQUEST_PATH<br> |
||
| 123 | CONTEXT_PATH<br> |
||
| 124 | SERVLET_PATH<br> |
||
| 125 | PATH_INFO<br> |
||
| 126 | QUERY_STRING<br> |
||
| 127 | AUTH_TYPE<br> |
||
| 128 | </p> |
||
| 129 | </li> |
||
| 130 | <li> |
||
| 131 | <p><b>server internals:</b></p> |
||
| 132 | <p> |
||
| 133 | DOCUMENT_ROOT<br> |
||
| 134 | SERVER_NAME<br> |
||
| 135 | SERVER_ADDR<br> |
||
| 136 | SERVER_PORT<br> |
||
| 137 | SERVER_PROTOCOL<br> |
||
| 138 | SERVER_SOFTWARE<br> |
||
| 139 | </p> |
||
| 140 | </li> |
||
| 141 | <li> |
||
| 142 | <p><b>date and time:</b></p> |
||
| 143 | <p> |
||
| 144 | TIME_YEAR<br> |
||
| 145 | TIME_MON<br> |
||
| 146 | TIME_DAY<br> |
||
| 147 | TIME_HOUR<br> |
||
| 148 | TIME_MIN<br> |
||
| 149 | TIME_SEC<br> |
||
| 150 | TIME_WDAY<br> |
||
| 151 | TIME<br> |
||
| 152 | </p> |
||
| 153 | </li> |
||
| 154 | <li> |
||
| 155 | <p><b>specials:</b></p> |
||
| 156 | <p> |
||
| 157 | THE_REQUEST<br> |
||
| 158 | REQUEST_URI<br> |
||
| 159 | REQUEST_FILENAME<br> |
||
| 160 | HTTPS<br> |
||
| 161 | </p> |
||
| 162 | </li> |
||
| 163 | </ul> |
||
| 164 | |||
| 165 | <p>These variables all |
||
| 166 | correspond to the similarly named HTTP |
||
| 167 | MIME-headers and Servlet API methods. |
||
| 168 | Most are documented elsewhere in the Manual or in |
||
| 169 | the CGI specification. Those that are special to |
||
| 170 | the rewrite valve include those below.</p> |
||
| 171 | |||
| 172 | <dl> |
||
| 173 | |||
| 174 | <dt><code>REQUEST_PATH</code></dt> |
||
| 175 | |||
| 176 | <dd>Corresponds to the full path that is used for mapping.</dd> |
||
| 177 | |||
| 178 | <dt><code>CONTEXT_PATH</code></dt> |
||
| 179 | |||
| 180 | <dd>Corresponds to the path of the mapped context.</dd> |
||
| 181 | |||
| 182 | <dt><code>SERVLET_PATH</code></dt> |
||
| 183 | |||
| 184 | <dd>Corresponds to the servlet path.</dd> |
||
| 185 | |||
| 186 | <dt><code>THE_REQUEST</code></dt> |
||
| 187 | |||
| 188 | <dd>The full HTTP request line sent by the |
||
| 189 | browser to the server (e.g., "<code>GET |
||
| 190 | /index.html HTTP/1.1</code>"). This does not |
||
| 191 | include any additional headers sent by the |
||
| 192 | browser.</dd> |
||
| 193 | |||
| 194 | <dt><code>REQUEST_URI</code></dt> |
||
| 195 | |||
| 196 | <dd>The resource requested in the HTTP request |
||
| 197 | line. (In the example above, this would be |
||
| 198 | "/index.html".)</dd> |
||
| 199 | |||
| 200 | <dt><code>REQUEST_FILENAME</code></dt> |
||
| 201 | |||
| 202 | <dd>The full local file system path to the file or |
||
| 203 | script matching the request.</dd> |
||
| 204 | |||
| 205 | <dt><code>HTTPS</code></dt> |
||
| 206 | |||
| 207 | <dd>Will contain the text "on" if the connection is |
||
| 208 | using SSL/TLS, or "off" otherwise.</dd> |
||
| 209 | |||
| 210 | </dl> |
||
| 211 | |||
| 212 | </li> |
||
| 213 | </ul> |
||
| 214 | |||
| 215 | <p>Other things you should be aware of:</p> |
||
| 216 | |||
| 217 | <ol> |
||
| 218 | <li>The variables SCRIPT_FILENAME and REQUEST_FILENAME |
||
| 219 | contain the same value - the value of the |
||
| 220 | <code>filename</code> field of the internal |
||
| 221 | <code>request_rec</code> structure of the Apache server. |
||
| 222 | The first name is the commonly known CGI variable name |
||
| 223 | while the second is the appropriate counterpart of |
||
| 224 | REQUEST_URI (which contains the value of the |
||
| 225 | <code>uri</code> field of <code>request_rec</code>).</li> |
||
| 226 | |||
| 227 | <li> |
||
| 228 | <code>%{ENV:variable}</code>, where <em>variable</em> can be |
||
| 229 | any Java system property, is also available.</li> |
||
| 230 | |||
| 231 | <li> |
||
| 232 | <code>%{SSL:variable}</code>, where <em>variable</em> is the |
||
| 233 | name of an SSL environment |
||
| 234 | variable, are implemented, except |
||
| 235 | <code>SSL_SESSION_RESUMED</code>, <code>SSL_SECURE_RENEG</code>, |
||
| 236 | <code>SSL_COMPRESS_METHOD</code>, <code>SSL_TLS_SNI</code>, |
||
| 237 | <code>SSL_SRP_USER</code>, <code>SSL_SRP_USERINFO</code>, |
||
| 238 | <code>SSL_CLIENT_VERIFY</code>, |
||
| 239 | <code>SSL_CLIENT_SAN_OTHER_msUPN_n</code>, |
||
| 240 | <code>SSL_CLIENT_CERT_RFC4523_CEA</code>, |
||
| 241 | <code>SSL_SERVER_SAN_OTHER_dnsSRV_n</code>. |
||
| 242 | When OpenSSL is used, the variables related to the server |
||
| 243 | certificate, prefixed by <code>SSL_SERVER_</code> are not available. |
||
| 244 | Example: |
||
| 245 | <code>%{SSL:SSL_CIPHER_USEKEYSIZE}</code> may expand to |
||
| 246 | <code>128</code>.</li> |
||
| 247 | |||
| 248 | <li> |
||
| 249 | <code>%{HTTP:header}</code>, where <em>header</em> can be |
||
| 250 | any HTTP MIME-header name, can always be used to obtain the |
||
| 251 | value of a header sent in the HTTP request. |
||
| 252 | Example: <code>%{HTTP:Proxy-Connection}</code> is |
||
| 253 | the value of the HTTP header |
||
| 254 | '<code>Proxy-Connection:</code>'.</li> |
||
| 255 | |||
| 256 | </ol> |
||
| 257 | |||
| 258 | <p><em>CondPattern</em> is the condition pattern, |
||
| 259 | a regular expression which is applied to the |
||
| 260 | current instance of the <em>TestString</em>. |
||
| 261 | <em>TestString</em> is first evaluated, before being matched against |
||
| 262 | <em>CondPattern</em>.</p> |
||
| 263 | |||
| 264 | <p><strong>Remember:</strong> <em>CondPattern</em> is a |
||
| 265 | <em>perl compatible regular expression</em> with some |
||
| 266 | additions:</p> |
||
| 267 | |||
| 268 | <ol> |
||
| 269 | <li>You can prefix the pattern string with a |
||
| 270 | '<code>!</code>' character (exclamation mark) to specify a |
||
| 271 | <strong>non</strong>-matching pattern.</li> |
||
| 272 | |||
| 273 | <li> |
||
| 274 | There are some special variants of <em>CondPatterns</em>. |
||
| 275 | Instead of real regular expression strings you can also |
||
| 276 | use one of the following: |
||
| 277 | |||
| 278 | <ul> |
||
| 279 | <li>'<strong><CondPattern</strong>' (lexicographically |
||
| 280 | precedes)<br> |
||
| 281 | Treats the <em>CondPattern</em> as a plain string and |
||
| 282 | compares it lexicographically to <em>TestString</em>. True if |
||
| 283 | <em>TestString</em> lexicographically precedes |
||
| 284 | <em>CondPattern</em>.</li> |
||
| 285 | |||
| 286 | <li>'<strong>>CondPattern</strong>' (lexicographically |
||
| 287 | follows)<br> |
||
| 288 | Treats the <em>CondPattern</em> as a plain string and |
||
| 289 | compares it lexicographically to <em>TestString</em>. True if |
||
| 290 | <em>TestString</em> lexicographically follows |
||
| 291 | <em>CondPattern</em>.</li> |
||
| 292 | |||
| 293 | <li>'<strong>=CondPattern</strong>' (lexicographically |
||
| 294 | equal)<br> |
||
| 295 | Treats the <em>CondPattern</em> as a plain string and |
||
| 296 | compares it lexicographically to <em>TestString</em>. True if |
||
| 297 | <em>TestString</em> is lexicographically equal to |
||
| 298 | <em>CondPattern</em> (the two strings are exactly |
||
| 299 | equal, character for character). If <em>CondPattern</em> |
||
| 300 | is <code>""</code> (two quotation marks) this |
||
| 301 | compares <em>TestString</em> to the empty string.</li> |
||
| 302 | |||
| 303 | <li>'<strong>-d</strong>' (is |
||
| 304 | <strong>d</strong>irectory)<br> |
||
| 305 | Treats the <em>TestString</em> as a pathname and tests |
||
| 306 | whether or not it exists, and is a directory.</li> |
||
| 307 | |||
| 308 | <li>'<strong>-f</strong>' (is regular |
||
| 309 | <strong>f</strong>ile)<br> |
||
| 310 | Treats the <em>TestString</em> as a pathname and tests |
||
| 311 | whether or not it exists, and is a regular file.</li> |
||
| 312 | |||
| 313 | <li>'<strong>-s</strong>' (is regular file, with |
||
| 314 | <strong>s</strong>ize)<br> |
||
| 315 | Treats the <em>TestString</em> as a pathname and tests |
||
| 316 | whether or not it exists, and is a regular file with size greater |
||
| 317 | than zero.</li> |
||
| 318 | |||
| 319 | </ul> |
||
| 320 | |||
| 321 | <strong>Note:</strong> |
||
| 322 | All of these tests can |
||
| 323 | also be prefixed by an exclamation mark ('!') to |
||
| 324 | negate their meaning. |
||
| 325 | |||
| 326 | </li> |
||
| 327 | |||
| 328 | <li>You can also set special flags for |
||
| 329 | <em>CondPattern</em> by appending |
||
| 330 | <strong><code>[</code><em>flags</em><code>]</code></strong> |
||
| 331 | as the third argument to the <code>RewriteCond</code> |
||
| 332 | directive, where <em>flags</em> is a comma-separated list of any of the |
||
| 333 | following flags: |
||
| 334 | |||
| 335 | <ul> |
||
| 336 | <li>'<strong><code>nocase|NC</code></strong>' |
||
| 337 | (<strong>n</strong>o <strong>c</strong>ase)<br> |
||
| 338 | This makes the test case-insensitive - differences |
||
| 339 | between 'A-Z' and 'a-z' are ignored, both in the |
||
| 340 | expanded <em>TestString</em> and the <em>CondPattern</em>. |
||
| 341 | This flag is effective only for comparisons between |
||
| 342 | <em>TestString</em> and <em>CondPattern</em>. It has no |
||
| 343 | effect on file system and subrequest checks.</li> |
||
| 344 | |||
| 345 | <li> |
||
| 346 | '<strong><code>ornext|OR</code></strong>' |
||
| 347 | (<strong>or</strong> next condition)<br> |
||
| 348 | Use this to combine rule conditions with a local OR |
||
| 349 | instead of the implicit AND. Typical example: |
||
| 350 | |||
| 351 | <div class="codeBox"><pre><code>RewriteCond %{REMOTE_HOST} ^host1.* [OR] |
||
| 352 | RewriteCond %{REMOTE_HOST} ^host2.* [OR] |
||
| 353 | RewriteCond %{REMOTE_HOST} ^host3.* |
||
| 354 | RewriteRule ...some special stuff for any of these hosts...</code></pre></div> |
||
| 355 | |||
| 356 | Without this flag you would have to write the condition/rule |
||
| 357 | pair three times. |
||
| 358 | </li> |
||
| 359 | </ul> |
||
| 360 | </li> |
||
| 361 | </ol> |
||
| 362 | |||
| 363 | <p><strong>Example:</strong></p> |
||
| 364 | |||
| 365 | <p>To rewrite the Homepage of a site according to the |
||
| 366 | '<code>User-Agent:</code>' header of the request, you can |
||
| 367 | use the following: </p> |
||
| 368 | |||
| 369 | <div class="codeBox"><pre><code>RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* |
||
| 370 | RewriteRule ^/$ /homepage.max.html [L] |
||
| 371 | |||
| 372 | RewriteCond %{HTTP_USER_AGENT} ^Lynx.* |
||
| 373 | RewriteRule ^/$ /homepage.min.html [L] |
||
| 374 | |||
| 375 | RewriteRule ^/$ /homepage.std.html [L]</code></pre></div> |
||
| 376 | |||
| 377 | <p>Explanation: If you use a browser which identifies itself |
||
| 378 | as 'Mozilla' (including Netscape Navigator, Mozilla etc), then you |
||
| 379 | get the max homepage (which could include frames, or other special |
||
| 380 | features). |
||
| 381 | If you use the Lynx browser (which is terminal-based), then |
||
| 382 | you get the min homepage (which could be a version designed for |
||
| 383 | easy, text-only browsing). |
||
| 384 | If neither of these conditions apply (you use any other browser, |
||
| 385 | or your browser identifies itself as something non-standard), you get |
||
| 386 | the std (standard) homepage.</p> |
||
| 387 | |||
| 388 | </div></div> |
||
| 389 | |||
| 390 | <div class="subsection"><h4 id="RewriteMap">RewriteMap</h4><div class="text"> |
||
| 391 | |||
| 392 | <p>Syntax: <code>RewriteMap name rewriteMapClassName optionalParameters</code></p> |
||
| 393 | |||
| 394 | <p>The <code>rewriteMapClassName</code> value also allows special values: |
||
| 395 | <ul> |
||
| 396 | <li><code>int:toupper</code>: Special map converting passed values to upper case</li> |
||
| 397 | <li><code>int:tolower</code>: Special map converting passed values to lower case</li> |
||
| 398 | <li><code>int:escape</code>: URL escape the passed value</li> |
||
| 399 | <li><code>int:unescape</code>: URL unescape the passed value</li> |
||
| 400 | </ul> |
||
| 401 | </p> |
||
| 402 | |||
| 403 | <p>The maps are implemented using an interface that users must implement. Its class |
||
| 404 | name is <code>org.apache.catalina.valves.rewrite.RewriteMap</code>, and its code is:</p> |
||
| 405 | |||
| 406 | <div class="codeBox"><pre><code>package org.apache.catalina.valves.rewrite; |
||
| 407 | |||
| 408 | public interface RewriteMap { |
||
| 409 | default String setParameters(String params...); // calls setParameters(String) with the first parameter if there is only one |
||
| 410 | public String setParameters(String params); |
||
| 411 | public String lookup(String key); |
||
| 412 | }</code></pre></div> |
||
| 413 | |||
| 414 | <p>The referenced implementation of such a class – in our example <code>rewriteMapClassName</code> – |
||
| 415 | will be instantiated and initialized with the optional parameter – <code>optionalParameters</code> from above |
||
| 416 | (be careful with whitespace) – by calling <code>setParameters(String)</code>. That instance |
||
| 417 | will then be registered under the name given as the first parameter of <code>RewriteMap</code> rule.</p> |
||
| 418 | |||
| 419 | <p>Note: Starting with Tomcat 9 you can use more than one parameter. These have to be separated by spaces. Parameters |
||
| 420 | can be quoted with ". This enables space characters inside parameters.</p> |
||
| 421 | |||
| 422 | <p>That map instance will be given the lookup value that is configured in the corresponding <code>RewriteRule</code> by |
||
| 423 | calling <code>lookup(String)</code>. Your implementation is free to return <code>null</code> to indicate, |
||
| 424 | that the given default should be used, or to return a replacement value.</p> |
||
| 425 | |||
| 426 | <p>Say, you want to implement a rewrite map function that converts all lookup keys to uppercase. You |
||
| 427 | would start by implementing a class that implements the <code>RewriteMap</code> interface.</p> |
||
| 428 | |||
| 429 | <div class="codeBox"><pre><code>package example.maps; |
||
| 430 | |||
| 431 | import org.apache.catalina.valves.rewrite.RewriteMap; |
||
| 432 | |||
| 433 | public class UpperCaseMap implements RewriteMap { |
||
| 434 | |||
| 435 | @Override |
||
| 436 | public String setParameters(String params) { |
||
| 437 | // nothing to be done here |
||
| 438 | return null; |
||
| 439 | } |
||
| 440 | |||
| 441 | @Override |
||
| 442 | public String lookup(String key) { |
||
| 443 | if (key == null) { |
||
| 444 | return null; |
||
| 445 | } |
||
| 446 | return key.toUpperCase(Locale.ENGLISH); |
||
| 447 | } |
||
| 448 | |||
| 449 | }</code></pre></div> |
||
| 450 | |||
| 451 | <p>Compile this class, put it into a jar and place that jar in <code>${CATALINA_BASE}/lib</code>.</p> |
||
| 452 | |||
| 453 | <p>Having done that, you can now define a map with the <code>RewriteMap</code> directive |
||
| 454 | and further on use that map in a <code>RewriteRule</code>.</p> |
||
| 455 | |||
| 456 | <div class="codeBox"><pre><code>RewriteMap uc example.maps.UpperCaseMap |
||
| 457 | |||
| 458 | RewriteRule ^/(.*)$ ${uc:$1} |
||
| 459 | </code></pre></div> |
||
| 460 | |||
| 461 | <p>With this setup a request to the url path <code>/index.html</code> would get routed |
||
| 462 | to <code>/INDEX.HTML</code>.</p> |
||
| 463 | </div></div> |
||
| 464 | |||
| 465 | <div class="subsection"><h4 id="RewriteRule">RewriteRule</h4><div class="text"> |
||
| 466 | |||
| 467 | <p>Syntax: <code>RewriteRule Pattern Substitution</code></p> |
||
| 468 | |||
| 469 | <p>The RewriteRule directive is the real |
||
| 470 | rewriting workhorse. The directive can occur more than once, |
||
| 471 | with each instance defining a single rewrite rule. The |
||
| 472 | order in which these rules are defined is important - this is the order |
||
| 473 | in which they will be applied at run-time.</p> |
||
| 474 | |||
| 475 | <p>Pattern is a perl compatible regular |
||
| 476 | expression, which is applied to the current URL. |
||
| 477 | 'Current' means the value of the URL when this rule is |
||
| 478 | applied. This may not be the originally requested URL, |
||
| 479 | which may already have matched a previous rule, and have been |
||
| 480 | altered.</p> |
||
| 481 | |||
| 482 | <p><strong>Security warning:</strong> Due to the way Java's |
||
| 483 | regex matching is done, poorly formed regex patterns are vulnerable |
||
| 484 | to "catastrophic backtracking", also known as "regular expression |
||
| 485 | denial of service" or ReDoS. Therefore, extra caution should be used |
||
| 486 | for RewriteRule patterns. In general it is difficult to automatically |
||
| 487 | detect such vulnerable regex, and so a good defense is to read a bit |
||
| 488 | on the subject of catastrophic backtracking. A good reference is the |
||
| 489 | <a href="https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS"> |
||
| 490 | OWASP ReDoS guide</a>.</p> |
||
| 491 | |||
| 492 | <p>Some hints on the syntax of regular |
||
| 493 | expressions:</p> |
||
| 494 | |||
| 495 | |||
| 496 | <pre> |
||
| 497 | <strong>Text:</strong> |
||
| 498 | <strong><code>.</code></strong> Any single character |
||
| 499 | <strong><code>[</code></strong>chars<strong><code>]</code></strong> Character class: Any character of the class 'chars' |
||
| 500 | <strong><code>[^</code></strong>chars<strong><code>]</code></strong> Character class: Not a character of the class 'chars' |
||
| 501 | text1<strong><code>|</code></strong>text2 Alternative: text1 or text2 |
||
| 502 | |||
| 503 | <strong>Quantifiers:</strong> |
||
| 504 | <strong><code>?</code></strong> 0 or 1 occurrences of the preceding text |
||
| 505 | <strong><code>*</code></strong> 0 or N occurrences of the preceding text (N > 0) |
||
| 506 | <strong><code>+</code></strong> 1 or N occurrences of the preceding text (N > 1) |
||
| 507 | |||
| 508 | <strong>Grouping:</strong> |
||
| 509 | <strong><code>(</code></strong>text<strong><code>)</code></strong> Grouping of text |
||
| 510 | (used either to set the borders of an alternative as above, or |
||
| 511 | to make backreferences, where the <strong>N</strong>th group can |
||
| 512 | be referred to on the RHS of a RewriteRule as <code>$</code><strong>N</strong>) |
||
| 513 | |||
| 514 | <strong>Anchors:</strong> |
||
| 515 | <strong><code>^</code></strong> Start-of-line anchor |
||
| 516 | <strong><code>$</code></strong> End-of-line anchor |
||
| 517 | |||
| 518 | <strong>Escaping:</strong> |
||
| 519 | <strong><code>\</code></strong>char escape the given char |
||
| 520 | (for instance, to specify the chars "<code>.[]()</code>" <em>etc.</em>) |
||
| 521 | </pre> |
||
| 522 | |||
| 523 | <p>For more information about regular expressions, have a look at the |
||
| 524 | perl regular expression manpage ("<a href="https://perldoc.perl.org/perlre.html">perldoc |
||
| 525 | perlre</a>"). If you are interested in more detailed |
||
| 526 | information about regular expressions and their variants |
||
| 527 | (POSIX regex etc.) the following book is dedicated to this topic:</p> |
||
| 528 | |||
| 529 | <p class="indent"> |
||
| 530 | <em>Mastering Regular Expressions, 2nd Edition</em><br> |
||
| 531 | Jeffrey E.F. Friedl<br> |
||
| 532 | O'Reilly & Associates, Inc. 2002<br> |
||
| 533 | ISBN 978-0-596-00289-3<br> |
||
| 534 | </p> |
||
| 535 | |||
| 536 | <p>In the rules, the NOT character |
||
| 537 | ('<code>!</code>') is also available as a possible pattern |
||
| 538 | prefix. This enables you to negate a pattern; to say, for instance: |
||
| 539 | '<em>if the current URL does <strong>NOT</strong> match this |
||
| 540 | pattern</em>'. This can be used for exceptional cases, where |
||
| 541 | it is easier to match the negative pattern, or as a last |
||
| 542 | default rule.</p> |
||
| 543 | |||
| 544 | <p> |
||
| 545 | Note: When using the NOT character to negate a pattern, you cannot include |
||
| 546 | grouped wildcard parts in that pattern. This is because, when the |
||
| 547 | pattern does NOT match (i.e., the negation matches), there are no |
||
| 548 | contents for the groups. Thus, if negated patterns are used, you |
||
| 549 | cannot use <code>$N</code> in the substitution string! |
||
| 550 | </p> |
||
| 551 | |||
| 552 | <p>The <em id="rhs">substitution</em> of a |
||
| 553 | rewrite rule is the string which is substituted for (or |
||
| 554 | replaces) the original URL which <em>Pattern</em> |
||
| 555 | matched. In addition to plain text, it can include</p> |
||
| 556 | |||
| 557 | <ol> |
||
| 558 | <li>back-references (<code>$N</code>) to the RewriteRule |
||
| 559 | pattern</li> |
||
| 560 | |||
| 561 | <li>back-references (<code>%N</code>) to the last matched |
||
| 562 | RewriteCond pattern</li> |
||
| 563 | |||
| 564 | <li>server-variables as in rule condition test-strings |
||
| 565 | (<code>%{VARNAME}</code>)</li> |
||
| 566 | |||
| 567 | <li><a href="#RewriteMap">mapping-function</a> calls |
||
| 568 | (<code>${mapname:key|default}</code>)</li> |
||
| 569 | </ol> |
||
| 570 | <p>Back-references are identifiers of the form |
||
| 571 | <code>$</code><strong>N</strong> |
||
| 572 | (<strong>N</strong>=0..9), which will be replaced |
||
| 573 | by the contents of the <strong>N</strong>th group of the |
||
| 574 | matched <em>Pattern</em>. The server-variables are the same |
||
| 575 | as for the <em>TestString</em> of a <code>RewriteCond</code> |
||
| 576 | directive. The mapping-functions come from the |
||
| 577 | <code>RewriteMap</code> directive and are explained there. |
||
| 578 | These three types of variables are expanded in the order above.</p> |
||
| 579 | |||
| 580 | <p>As already mentioned, all rewrite rules are |
||
| 581 | applied to the <em>Substitution</em> (in the order in which |
||
| 582 | they are defined |
||
| 583 | in the config file). The URL is <strong>completely |
||
| 584 | replaced</strong> by the <em>Substitution</em> and the |
||
| 585 | rewriting process continues until all rules have been applied, |
||
| 586 | or it is explicitly terminated by a |
||
| 587 | <code><strong>L</strong></code> flag.</p> |
||
| 588 | |||
| 589 | <p>The special characters <code>$</code> and <code>%</code> can |
||
| 590 | be quoted by prepending them with a backslash character |
||
| 591 | <code>\</code>.</p> |
||
| 592 | |||
| 593 | <p>There is a special substitution string named |
||
| 594 | '<code>-</code>' which means: <strong>NO |
||
| 595 | substitution</strong>! This is useful in providing |
||
| 596 | rewriting rules which <strong>only</strong> match |
||
| 597 | URLs but do not substitute anything for them. It is commonly used |
||
| 598 | in conjunction with the <strong>C</strong> (chain) flag, in order |
||
| 599 | to apply more than one pattern before substitution occurs.</p> |
||
| 600 | |||
| 601 | <p>Unlike newer mod_rewrite versions, the Tomcat rewrite valve does |
||
| 602 | not automatically support absolute URLs (the specific redirect flag |
||
| 603 | must be used to be able to specify an absolute URLs, see below) |
||
| 604 | or direct file serving.</p> |
||
| 605 | |||
| 606 | <p>Additionally you can set special <span id="rewriteflags">flags</span> for <em>Substitution</em> by |
||
| 607 | appending <strong><code>[</code><em>flags</em><code>]</code></strong> |
||
| 608 | as the third argument to the <code>RewriteRule</code> |
||
| 609 | directive. <em>Flags</em> is a comma-separated list of any of the |
||
| 610 | following flags: </p> |
||
| 611 | |||
| 612 | <ul> |
||
| 613 | <li>'<strong><code>chain|C</code></strong>' |
||
| 614 | (<strong>c</strong>hained with next rule)<br> |
||
| 615 | This flag chains the current rule with the next rule |
||
| 616 | (which itself can be chained with the following rule, |
||
| 617 | and so on). This has the following effect: if a rule |
||
| 618 | matches, then processing continues as usual - |
||
| 619 | the flag has no effect. If the rule does |
||
| 620 | <strong>not</strong> match, then all following chained |
||
| 621 | rules are skipped. For instance, it can be used to remove the |
||
| 622 | '<code>.www</code>' part, inside a per-directory rule set, |
||
| 623 | when you let an external redirect happen (where the |
||
| 624 | '<code>.www</code>' part should not occur!).</li> |
||
| 625 | |||
| 626 | <li> |
||
| 627 | '<strong><code>cookie|CO=</code></strong><em>NAME</em>:<em>VAL</em>:<em>domain</em>[:<em>lifetime</em>[:<em>path</em>]]' |
||
| 628 | (set <strong>co</strong>okie)<br> |
||
| 629 | This sets a cookie in the client's browser. The cookie's name |
||
| 630 | is specified by <em>NAME</em> and the value is |
||
| 631 | <em>VAL</em>. The <em>domain</em> field is the domain of the |
||
| 632 | cookie, such as '.apache.org', the optional <em>lifetime</em> |
||
| 633 | is the lifetime of the cookie in minutes, and the optional |
||
| 634 | <em>path</em> is the path of the cookie</li> |
||
| 635 | |||
| 636 | <li> |
||
| 637 | '<strong><code>env|E=</code></strong><em>VAR</em>:<em>VAL</em>' |
||
| 638 | (set <strong>e</strong>nvironment variable)<br> |
||
| 639 | This forces a request attribute named <em>VAR</em> to |
||
| 640 | be set to the value <em>VAL</em>, where <em>VAL</em> can |
||
| 641 | contain regexp backreferences (<code>$N</code> and |
||
| 642 | <code>%N</code>) which will be expanded. You can use this |
||
| 643 | flag more than once, to set more than one variable.</li> |
||
| 644 | |||
| 645 | <li>'<strong><code>forbidden|F</code></strong>' (force URL |
||
| 646 | to be <strong>f</strong>orbidden)<br> |
||
| 647 | This forces the current URL to be forbidden - it immediately |
||
| 648 | sends back an HTTP response of 403 (FORBIDDEN). |
||
| 649 | Use this flag in conjunction with |
||
| 650 | appropriate RewriteConds to conditionally block some |
||
| 651 | URLs.</li> |
||
| 652 | |||
| 653 | <li>'<strong><code>gone|G</code></strong>' (force URL to be |
||
| 654 | <strong>g</strong>one)<br> |
||
| 655 | This forces the current URL to be gone - it |
||
| 656 | immediately sends back an HTTP response of 410 (GONE). Use |
||
| 657 | this flag to mark pages which no longer exist as gone.</li> |
||
| 658 | |||
| 659 | <li> |
||
| 660 | '<strong><code>host|H</code></strong>=<em>Host</em>' |
||
| 661 | (apply rewriting to <strong>h</strong>ost)<br> |
||
| 662 | Rather that rewrite the URL, the virtual host will be |
||
| 663 | rewritten.</li> |
||
| 664 | |||
| 665 | <li>'<strong><code>last|L</code></strong>' |
||
| 666 | (<strong>l</strong>ast rule)<br> |
||
| 667 | Stop the rewriting process here and don't apply any more |
||
| 668 | rewrite rules. This corresponds to the Perl |
||
| 669 | <code>last</code> command or the <code>break</code> command |
||
| 670 | in C. Use this flag to prevent the currently |
||
| 671 | rewritten URL from being rewritten further by following |
||
| 672 | rules. For example, use it to rewrite the root-path URL |
||
| 673 | ('<code>/</code>') to a real one, <em>e.g.</em>, |
||
| 674 | '<code>/e/www/</code>'.</li> |
||
| 675 | |||
| 676 | <li>'<strong><code>next|N</code></strong>' |
||
| 677 | (<strong>n</strong>ext round)<br> |
||
| 678 | Re-run the rewriting process (starting again with the |
||
| 679 | first rewriting rule). This time, the URL to match is no longer |
||
| 680 | the original URL, but rather the URL returned by the last rewriting rule. |
||
| 681 | This corresponds to the Perl <code>next</code> command or |
||
| 682 | the <code>continue</code> command in C. Use |
||
| 683 | this flag to restart the rewriting process - |
||
| 684 | to immediately go to the top of the loop.<br> |
||
| 685 | <strong>Be careful not to create an infinite |
||
| 686 | loop!</strong></li> |
||
| 687 | |||
| 688 | <li>'<strong><code>nocase|NC</code></strong>' |
||
| 689 | (<strong>n</strong>o <strong>c</strong>ase)<br> |
||
| 690 | This makes the <em>Pattern</em> case-insensitive, |
||
| 691 | ignoring difference between 'A-Z' and |
||
| 692 | 'a-z' when <em>Pattern</em> is matched against the current |
||
| 693 | URL.</li> |
||
| 694 | |||
| 695 | <li> |
||
| 696 | '<strong><code>noescape|NE</code></strong>' |
||
| 697 | (<strong>n</strong>o URI <strong>e</strong>scaping of |
||
| 698 | output)<br> |
||
| 699 | This flag prevents the rewrite valve from applying the usual URI |
||
| 700 | escaping rules to the result of a rewrite. Ordinarily, |
||
| 701 | special characters (such as '%', '$', ';', and so on) |
||
| 702 | will be escaped into their hexcode equivalents ('%25', |
||
| 703 | '%24', and '%3B', respectively); this flag prevents this |
||
| 704 | from happening. This allows percent symbols to appear in |
||
| 705 | the output, as in |
||
| 706 | <div class="codeBox"><pre><code>RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]</code></pre></div> |
||
| 707 | which would turn '<code>/foo/zed</code>' into a safe |
||
| 708 | request for '<code>/bar?arg=P1=zed</code>'. |
||
| 709 | </li> |
||
| 710 | |||
| 711 | |||
| 712 | |||
| 713 | <li>'<strong><code>qsappend|QSA</code></strong>' |
||
| 714 | (<strong>q</strong>uery <strong>s</strong>tring |
||
| 715 | <strong>a</strong>ppend)<br> |
||
| 716 | This flag forces the rewrite engine to append a query |
||
| 717 | string part of the substitution string to the existing string, |
||
| 718 | instead of replacing it. Use this when you want to add more |
||
| 719 | data to the query string via a rewrite rule.</li> |
||
| 720 | |||
| 721 | <li>'<strong><code>redirect|R</code> |
||
| 722 | [=<em>code</em>]</strong>' (force <span id="redirect"> |
||
| 723 | <strong>r</strong>edirect</span>)<br> |
||
| 724 | Prefix <em>Substitution</em> with |
||
| 725 | <code>http://thishost[:thisport]/</code> (which makes the |
||
| 726 | new URL a URI) to force an external redirection. If no |
||
| 727 | <em>code</em> is given, an HTTP response of 302 (FOUND, previously MOVED |
||
| 728 | TEMPORARILY) will be returned. If you want to use other response |
||
| 729 | codes in the range 300-399, simply specify the appropriate number |
||
| 730 | or use one of the following symbolic names: |
||
| 731 | <code>temp</code> (default), <code>permanent</code>, |
||
| 732 | <code>seeother</code>. Use this for rules to |
||
| 733 | canonicalize the URL and return it to the client - to |
||
| 734 | translate '<code>/~</code>' into |
||
| 735 | '<code>/u/</code>', or to always append a slash to |
||
| 736 | <code>/u/</code><em>user</em>, etc.<br> |
||
| 737 | <strong>Note:</strong> When you use this flag, make |
||
| 738 | sure that the substitution field is a valid URL! Otherwise, |
||
| 739 | you will be redirecting to an invalid location. Remember |
||
| 740 | that this flag on its own will only prepend |
||
| 741 | <code>http://thishost[:thisport]/</code> to the URL, and rewriting |
||
| 742 | will continue. Usually, you will want to stop rewriting at this point, |
||
| 743 | and redirect immediately. To stop rewriting, you should add |
||
| 744 | the 'L' flag. |
||
| 745 | </li> |
||
| 746 | |||
| 747 | <li>'<strong><code>skip|S</code></strong>=<em>num</em>' |
||
| 748 | (<strong>s</strong>kip next rule(s))<br> |
||
| 749 | This flag forces the rewriting engine to skip the next |
||
| 750 | <em>num</em> rules in sequence, if the current rule |
||
| 751 | matches. Use this to make pseudo if-then-else constructs: |
||
| 752 | The last rule of the then-clause becomes |
||
| 753 | <code>skip=N</code>, where N is the number of rules in the |
||
| 754 | else-clause. (This is <strong>not</strong> the same as the |
||
| 755 | 'chain|C' flag!)</li> |
||
| 756 | |||
| 757 | <li> |
||
| 758 | '<strong><code>type|T</code></strong>=<em>MIME-type</em>' |
||
| 759 | (force MIME <strong>t</strong>ype)<br> |
||
| 760 | Force the MIME-type of the target file to be |
||
| 761 | <em>MIME-type</em>. This can be used to |
||
| 762 | set up the content-type based on some conditions. |
||
| 763 | For example, the following snippet allows <code>.php</code> files to |
||
| 764 | be <em>displayed</em> by <code>mod_php</code> if they are called with |
||
| 765 | the <code>.phps</code> extension: |
||
| 766 | <div class="codeBox"><pre><code>RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]</code></pre></div> |
||
| 767 | </li> |
||
| 768 | |||
| 769 | <li>'<strong><code>valveSkip|VS</code></strong>' |
||
| 770 | (skip valve)<br> |
||
| 771 | This flag can be used to setup conditional execution of valves. |
||
| 772 | When the flag is set and the rule matches, the rewrite valve will skip |
||
| 773 | the next valve in the Catalina pipeline. If the rewrite valve is the |
||
| 774 | last of the pipeline, then the flag will be ignored and the container |
||
| 775 | basic valve will be invoked. If rewrite occurred, then the flag will |
||
| 776 | not have any effect. |
||
| 777 | </li> |
||
| 778 | |||
| 779 | </ul> |
||
| 780 | |||
| 781 | </div></div> |
||
| 782 | |||
| 783 | </div></div></div></div></div><footer><div id="footer"> |
||
| 784 | Copyright © 1999-2025, The Apache Software Foundation |
||
| 785 | <br> |
||
| 786 | Apache Tomcat, Tomcat, Apache, the Apache Tomcat logo and the Apache logo |
||
| 787 | are either registered trademarks or trademarks of the Apache Software |
||
| 788 | Foundation. |
||
| 789 | </div></footer></div></body></html> |