Permalink
Browse files

Adding manual of URL Rewriter Filter 4.0

  • Loading branch information...
1 parent 3cab614 commit c636591386ee945cabce7e5af6f8e325416feddf @Kdecherf Kdecherf committed Aug 29, 2010
View
161 doc/urlrewritefilter/annotation.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<head>
+ <title>UrlRewriteFilter - Annotation</title>
+ <style type="text/css">
+ @import url( "doc.css" );
+ </style>
+</head>
+
+<body>
+
+<div id="masthead">
+ <a href="http://tuckey.org/urlrewrite/">
+ <img id="logo" src="urf.gif" border="0" alt="Tuckey Logo" />
+ Url Rewrite Filter <!--@ver-->4.0.0<!--/@ver--></a>
+</div>
+
+<div id="menu">
+<ul>
+ <li><a href="http://tuckey.org/urlrewrite/">Home</a></li>
+ <li><a href="http://tuckey.org/urlrewrite/#download">Download</a></li>
+ <li><a href="http://code.google.com/p/urlrewritefilter/source">svn access</a></li>
+ <li><a href="http://groups.google.com/group/urlrewrite">UrlRewrite google group</a><br/>&nbsp;</li>
+
+ <li><b>Background</b>
+ <ul>
+ <li><a href="introduction.html#license">License</a></li>
+ <li><a href="introduction.html#changelog">Changelog</a></li>
+ </ul>
+ </li>
+ <li><a href="index.html">Configuration</a>
+ <ul>
+ <li><a href="index.html#install">Install</a></li>
+ <li><a href="index.html#tips">Tips</a></li>
+ <li><a href="index.html#filterparams">Filter Parameters</a></li>
+ <li><a href="index.html#configuration">Configuration File</a></li>
+ <li><a href="index.html#anttask">Ant Task</a></li>
+ <li><a href="index.html#mod_rewrite_conf">mod_rewrite Style</a></li>
+ </ul>
+ </li>
+ <li><b>Annotations</b></li>
+ <li><a href="guide.html">Examples</a>
+ <ul>
+ <li><a href="guide.html#method">Method Invocation</a></li>
+ <li><a href="guide.html#urlabs">URL Abstraction</a></li>
+ <li><a href="guide.html#mod_re">mod_rewrite vs UrlRewriteFilter</a></li>
+ </ul>
+ </li>
+</ul>
+</div>
+
+<div id="main">
+
+ <h1>URL Matching Annotations</h1>
+
+<a name="annotation"></a>
+
+<p>Support for annotations has been added as part of version 3 development. You must be using JDK 1.6 for this to work.</p>
+
+ <p>The intention of annotations in UrlRewriteFilter is purely for conf file generation. The is NO runtime
+ dependency on the annotations.</p>
+
+ <h2>Annotations</h2>
+
+ <h3>@HttpUrl</h3>
+
+ <p>Set the method up to be used when the url is Matched, matched groups are assigned to method paramters (if any).</p>
+
+ <pre><code>
+ @HttpUrl("^/do-something/([0-9]+)$")
+ public void doSomething(Long id)
+ </code></pre>
+
+ <p>When a request for /do-something/1234, doSomething is called with id set to 1234.</p>
+
+ <h3>@HttpParam</h3>
+
+ <p>Sets the parameter from request.getParameter (handles type conversion as necessary)</p>
+
+ <pre><code>
+ void doSomething(@HttpParam String name, @HttpParam long id, @HttpParam("uid") Long userId)
+ </code></pre>
+
+ <p>The above example will:
+ <br/>name = request.getParameter("name");
+ <br/>id = convertTolongDefault0(request.getParameter("id"));
+ <br/>userId = convertToLongDefaultNull(request.getParameter("uid"));
+ <br/>An exception will never be thown during type conversion
+ </p>
+
+
+
+
+<h2>Conf Generation</h2>
+
+ <p>With Java 1.6 the javac tool handles annotation processing. So this means all you need to do is have a
+ "urlrewriteDest" option specified and have urlrewritefilter jar in your classpath. Example of compilerarg
+ elements that would be used with javac ant task:</p>
+
+<pre><code>
+&lt;compilerarg line="-AurlrewriteDest=build/WEB-INF/urlrewrite-generated.xml"/&gt;
+<span style="color: gray;">&lt;!-- optional arguments
+&lt;compilerarg value="-AurlrewriteShowPositions=true"/&gt;
+&lt;compilerarg value="-AurlrewriteDebug=true"/&gt;
+--&gt;</span>
+</code></pre>
+
+ <p>An example compile ant task with urlrewrite option might look like:</p>
+
+<pre><code>
+<span style="color: gray;">&lt;target name="compile-urlrewrite-conf"&gt;
+ &lt;javac srcdir=&quot;src/&quot; destdir=&quot;build/WEB-INF/classes&quot;&gt;
+ &lt;classpath refid=&quot;compile.classpath&quot;/&gt;</span>
+ &lt;classpath path=&quot;lib/urlrewrite-<!--@ver-->3.2.0<!--/@ver-->.jar&quot;/&gt;
+ &lt;compilerarg line=&quot;-AurlrewriteDest=build/WEB-INF/urlrewrite-generated.xml&quot;/&gt;
+ <span style="color: gray;">&lt;/javac&gt;</span>
+ &lt;!-- check file generated ok (if not you may be using the wrong jdk version)--&gt;
+ &lt;available property=&quot;urlrewrite.generated&quot; file=&quot;build/WEB-INF/urlrewrite-generated.xml&quot;/&gt;
+ &lt;fail unless=&quot;urlrewrite.generated&quot; /&gt;
+<span style="color: gray;">&lt;/target&gt;</span>
+</code></pre>
+
+ <p>This will generate to the file specified. Any errors will be output to stdout using the standard APT method.
+ Read the generated conf file and check it for errors.</p>
+
+
+<p>Include the compiled conf file in your normal conf.</p>
+
+<pre><code>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
+ "http://tuckey.org/res/dtds/urlrewrite4.0.dtd"
+[
+ &lt;!ENTITY included SYSTEM "urlrewrite-generated.xml"&gt;
+]&gt;
+&lt;urlrewrite&gt;
+
+ &lt;!--
+ other rules...
+ --&gt;
+
+ &amp;included;
+
+
+&lt;/urlrewrite&gt;
+</code></pre>
+
+
+<p>Check your /rewrite-status for errors if things start going strange.</p>
+
+</div>
+
+<div id="footer">
+Copyright Paul Tuckey <!--@year-->2010<!--/@year-->
+ - <a href="http://tuckey.org/urlrewrite/">UrlRewirteFilter</a>
+</div>
+
+</body>
+</html>
+
View
131 doc/urlrewritefilter/doc.css
@@ -0,0 +1,131 @@
+body {
+ background: #c0c0c0;
+ font: 13px arial, helvetica, sans-serif;
+}
+
+#logo {
+ vertical-align: middle;
+}
+
+h1 {
+ color: #000000;
+ font-size: 2.5em;
+ padding: 0px 0px 0px 5px;
+ margin: 0px;
+ font-family: georgia, times, serif;
+}
+
+#masthead {
+ font-family: georgia, times, serif;
+ font-size: 3.5em;
+ background-color: #efefef;
+ -moz-border-radius-topright: 20px;
+ margin-top: 5px;
+ padding: 5px;
+ padding-left: 15px;
+ width: 650px;
+}
+
+#masthead a {
+ text-decoration: none;
+ color: black;
+}
+
+
+h2 {
+ font-family: georgia, times, serif;
+ border-bottom: 1px solid #808080;
+ padding: 5px;
+}
+
+h3 {
+ font-family: georgia, times, serif;
+ border-bottom: 1px solid #c0c0c0;
+ margin-top: 2em;
+ padding: 0.25em 0.25em 0em 0.5em;
+}
+
+p {
+ padding: 0.25em 0.25em 0em 1.0em;
+}
+
+code, pre {
+ font-family: 'Courier New', courier, monospace;
+ font-size: 11px;
+}
+
+pre {
+ background: #eeeeff;
+ margin: 0.5em 3em 0.1em 3em;
+ padding: 0.25em 0.5em 0.5em 0.5em;
+}
+
+table {
+ border: 1px solid #c0c0c0;
+ margin-left: 2em;
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+th, td {
+ border: 1px solid #eeeeee;
+ vertical-align: top;
+ padding: 3px;
+}
+
+th {
+ background: #eeeeee;
+}
+
+hr {
+ border: 0px;
+ background-color: #c0c0c0;
+}
+
+.err {
+ color: #ff0000;
+}
+
+#menu {
+ float:left;
+ width:160px;
+ background: #efefef;
+ Zmargin-top: 2px;
+ padding-bottom: 10px;
+ padding-left: 10px;
+ -moz-border-radius-bottomleft: 20px;
+}
+
+#menu ul {
+ list-style-type: none;
+ margin-left: .5em;
+ padding-left: .5em;
+ margin-top: 7px;
+}
+#menu li {
+ margin-bottom: 7px;
+}
+
+#main {
+ background: white;
+ border-left: 1px solid #c0c0c0;
+ border-top: 1px solid #c0c0c0;
+ border-right: 1px solid #808080;
+ border-bottom: 1px solid #808080;
+ margin-left: 170px;
+ padding: 15px;
+ -moz-border-radius-bottomleft: 20px;
+ min-height: 400px;
+}
+
+#footer {
+ margin-top: 40px;
+ text-align: center;
+ font-size: small;
+ color: black;
+ text-transform: lowercase;
+}
+
+#footer a {
+ text-decoration: none;
+}
View
780 doc/urlrewritefilter/guide.html
@@ -0,0 +1,780 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<head>
+ <title>UrlRewriteFilter - Examples</title>
+ <style type="text/css">
+ @import url( "doc.css" );
+ </style>
+</head>
+
+<body>
+
+<div id="masthead">
+ <a href="http://tuckey.org/urlrewrite/">
+ <img id="logo" src="urf.gif" border="0" alt="Tuckey Logo" />
+ Url Rewrite Filter <!--@ver-->4.0.0<!--/@ver--></a>
+</div>
+
+<div id="menu">
+<ul>
+ <li><a href="http://tuckey.org/urlrewrite/">Home</a></li>
+ <li><a href="http://tuckey.org/urlrewrite/#download">Download</a></li>
+ <li><a href="http://code.google.com/p/urlrewritefilter/source">svn access</a></li>
+ <li><a href="http://groups.google.com/group/urlrewrite">UrlRewrite google group</a><br/>&nbsp;</li>
+
+ <li><a href="introduction.html">Background</a>
+ <ul>
+ <li><a href="introduction.html#license">License</a></li>
+ <li><a href="introduction.html#changelog">Changelog</a></li>
+ </ul>
+ </li>
+ <li><a href="index.html">Configuration</a>
+ <ul>
+ <li><a href="index.html#install">Install</a></li>
+ <li><a href="index.html#tips">Tips</a></li>
+ <li><a href="index.html#filterparams">Filter Parameters</a></li>
+ <li><a href="index.html#configuration">Configuration File</a></li>
+ <li><a href="index.html#anttask">Ant Task</a></li>
+ <li><a href="index.html#mod_rewrite_conf">mod_rewrite Style</a></li>
+ </ul>
+ </li>
+ <li><a href="annotation.html">Annotations</a></li>
+ <li><b>Examples</b>
+ <ul>
+ <li><a href="guide.html#method">Method Invocation</a></li>
+ <li><a href="guide.html#urlabs">URL Abstraction</a></li>
+ <li><a href="guide.html#mod_re">mod_rewrite vs UrlRewriteFilter</a></li>
+ </ul>
+ </li>
+</ul>
+</div>
+
+<div id="main">
+
+
+<h1>Examples</h1>
+
+<p>Redirect one url</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/some/old/page\.html$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/very/new/page.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<pre><code>
+ &lt;rule match-type="wildcard"&gt;
+ &lt;from&gt;/some/old/page.html&lt;/from&gt;
+ &lt;to type="redirect"&gt;/very/new/page.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Redirect docs in a directory to another using wildcard engine.</p>
+
+<pre><code>
+ &lt;urlrewrite default-match-type="wildcard"&gt;
+
+ &lt;rule&gt;
+ &lt;from&gt;/some/old/*.doc&lt;/from&gt;
+ &lt;to type="redirect"&gt;/very/new/$1.doc&lt;/to&gt;
+ &lt;/rule&gt;
+
+ &lt;/urlrewrite&gt;
+</code></pre>
+
+<p>Tiny/Freindly url</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/zebra$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/big/ugly/url/1,23,56,23132.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Default page as another (requests to / will be redirected)</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/opencms/opencms/index.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Perform security checks in a centralised place</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition type="user-in-role" operator="notequal"&gt;admin&lt;/condition&gt;
+ &lt;condition type="user-in-role" operator="notequal"&gt;bigboss&lt;/condition&gt;
+ &lt;from&gt;^/admin/(.*)$&lt;/from&gt;
+ &lt;to&gt;/go-away-please.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<p>Check that users are using the correct domain name to get to your site. ie, users gong to http://example.com/blah
+ will be redirected to http://www.example.com/blah</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;name&gt;Domain Name Check&lt;/name&gt;
+ &lt;condition name="host" operator="notequal"&gt;www.example.com&lt;/condition&gt;
+ &lt;from&gt;^(.*)$&lt;/from&gt;
+ &lt;to type="redirect"&gt;http://www.example.com/context$1&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<p>Disable access to a directory.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;name&gt;Disable Directory&lt;/name&gt;
+ &lt;from&gt;^/notliveyet/.*$&lt;/from&gt;
+ &lt;set type="status"&gt;403&lt;/set&gt;
+ &lt;to&gt;null&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Redirect a directory (for moved content)</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/some/olddir/(.*)$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/very/newdir/$1&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Clean a URL</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/products/([0-9]+)$&lt;/from&gt;
+ &lt;to&gt;/products/index.jsp?product_id=$1&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>e.g. <code>/products/1234</code> will be passed on to <code>/products/index.jsp?product_id=1234</code>
+ without the user noticing.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/world/([a-z]+)/([a-z]+)$&lt;/from&gt;
+ &lt;to&gt;/world.jsp?country=$1&amp;amp;city=$2&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>e.g. <code>/world/unitedstates/newyork</code> will be passed on to <code>/world.jsp?country=unitedstates&amp;city=newyork</code>
+</p>
+
+<p>Browser detection</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition name="user-agent"&gt;Mozilla/[1-4]&lt;/condition&gt;
+ &lt;from&gt;^/some/page\.html$&lt;/from&gt;
+ &lt;to&gt;/some/page-for-old-browsers.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>e.g. will pass the request for <code>/some/page.html</code> on to <code>/some/page-for-old-browsers.html</code>
+ only for older browsers whose user agent strings match <code>Mozilla/1</code>, <code>Mozilla/2</code>,
+ <code>Mozilla/3</code> or <code>Mozilla/4</code>.</p>
+
+
+<p>Security. Preclude certain types of method from you web application.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition type="method" next="or"&gt;PROPFIND&lt;/condition&gt;
+ &lt;condition type="method"&gt;PUT&lt;/condition&gt;
+ &lt;from&gt;.*&lt;/from&gt;
+ &lt;to type="redirect"&gt;/bad-method.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<p>Sunday Specials</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition type="dayofweek"&gt;1&lt;/condition&gt;
+ &lt;from&gt;^/products/$&lt;/from&gt;
+ &lt;to&gt;/products/sunday-specials.html&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<p>Set the "Cache-Control" HTTP response header for all requests</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;.*&lt;/from&gt;
+ &lt;set type="response-header" name="Cache-Control"&gt;max-age=3600, must-revalidate&lt;/set&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Forward a request to a servlet</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/products/purchase$&lt;/from&gt;
+ &lt;to&gt;/servlets/ProductsServlet&lt;/to&gt;
+ &lt;set name="action"&gt;purchase&lt;/set&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>e.g. the request <code>/products/purchase</code> will be forwarded to <code>/servlets/ProductsServlet</code> and
+ inside
+ the servlet <code>request.getAttribute("action")</code> will return <code>purchase</code>.</p>
+
+<p>Set an "Expires" HTTP header 6 hours into the future for js, css and gif files</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^.*\.(js|css|gif)$&lt;/from&gt;
+ &lt;set type="expires"&gt;6 hours&lt;/set&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Hide jsessionid for requests from googlebot.</p>
+
+<pre><code>
+ &lt;outbound-rule&gt;
+ &lt;name&gt;Strip URL Session ID's&lt;/name&gt;
+ &lt;note&gt;
+ Strip ;jsession=XXX from urls passed through
+response.encodeURL().
+ The characters ? and # are the only things we can use to
+find out where the jsessionid ends.
+ The expression in 'from' below contains three capture
+groups, the last two being optional.
+ 1, everything before ;jesessionid
+ 2, everything after ;jesessionid=XXX starting with a ?
+(to get the query string) up to #
+ 3, everything ;jesessionid=XXX and optionally ?XXX
+starting with a # (to get the target)
+ eg,
+ from index.jsp;jsessionid=sss?qqq to index.jsp?qqq
+ from index.jsp;jsessionid=sss?qqq#ttt to index.jsp?qqq#ttt
+ from index.jsp;jsessionid=asdasdasdsadsadasd#dfds -
+index.jsp#dfds
+ from u.jsp;jsessionid=wert.hg - u.jsp
+ from /;jsessionid=tyu - /
+ &lt;/note&gt;
+ &lt;condition name="user-agent"&gt;googlebot&lt;/condition&gt;
+ &lt;from&gt;^(.*?)(?:\;jsessionid=[^\?#]*)?(\?[^#]*)?(#.*)?$&lt;/from&gt;
+ &lt;to&gt;$1$2$3&lt;/to&gt;
+ &lt;/outbound-rule&gt;
+</code></pre>
+
+<p>Permanently redirect incoming URLs containing jsessionid.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;name&gt;Strip URL Session ID's&lt;/name&gt;
+ &lt;note&gt;
+ Strip ;jsession=XXX from urls passed through
+response.encodeURL().
+ The characters ? and # are the only things we can use to
+find out where the jsessionid ends.
+ The expression in 'from' below contains three capture
+groups, the last two being optional.
+ 1, everything before ;jesessionid
+ 2, everything after ;jesessionid=XXX starting with a ?
+(to get the query string) up to #
+ 3, everything ;jesessionid=XXX and optionally ?XXX
+starting with a # (to get the target)
+ eg,
+ from index.jsp;jsessionid=sss?qqq to index.jsp?qqq
+ from index.jsp;jsessionid=sss?qqq#ttt to index.jsp?qqq#ttt
+ from index.jsp;jsessionid=asdasdasdsadsadasd#dfds -
+index.jsp#dfds
+ from u.jsp;jsessionid=wert.hg - u.jsp
+ from /;jsessionid=tyu - /
+ &lt;/note&gt;
+ &lt;condition type="requested-session-id-from-url" operator="equal"&gt;true&lt;/condition&gt;
+ &lt;from&gt;^(.*?)(?:\;jsessionid=[^\?#]*)?(\?[^#]*)?(#.*)?$&lt;/from&gt;
+ &lt;to type="permanent-redirect"&gt;$1$2$3&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<a name="method"></a>
+
+<h2>Method Invocation</h2>
+
+<p>The standard servlet mapping that is done via web.xml is rather limiting. Only *.xxx or /xxxx/*, no abilty to have
+ any sort of smart matching. Using UrlRewriteFilter any rule when matched can be set to run method(s) on a class.</p>
+
+<p>Invoke a servlet directly</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/products/purchase$&lt;/from&gt;
+ &lt;run class="com.blah.web.MyServlet" method="doGet" /&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>This will invoke <code>doGet(HttpServletRequest request, HttpServletResponse response)</code> when the "from" is
+ matched on a request. (remeber this method needs to be public!)</p>
+
+<p>Use it to delagate cleanly to your methods</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/pref-editor/addresses$&lt;/from&gt;
+ &lt;run class="com.blah.web.PrefsServlet" method="runAddresses" /&gt;
+ &lt;/rule&gt;
+ &lt;rule&gt;
+ &lt;from&gt;^/pref-editor/phone-nums$&lt;/from&gt;
+ &lt;run class="com.blah.web.PrefsServlet" method="runPhoneNums" /&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Browser based delagation to your methods</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition name="user-agent"&gt;Mozilla/[1-4]&lt;/condition&gt;
+ &lt;from&gt;^/content/.*$&lt;/from&gt;
+ &lt;run class="com.blah.web.ContentServlet" method="runForOldBrowsers" /&gt;
+ &lt;/rule&gt;
+ &lt;rule&gt;
+ &lt;condition name="user-agent" operator="notequal"&gt;Mozilla/[1-4]&lt;/condition&gt;
+ &lt;from&gt;^/content/.*$&lt;/from&gt;
+ &lt;run class="com.blah.web.GeneralServlet" method="runRobotMonitor" /&gt;
+ &lt;run class="com.blah.web.ContentServlet" method="runForNewBrowsers" /&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>When the method specified in the "run" is invoked it has full control over the request and response as if it were a
+ servlet.</p>
+
+<!--
+Note, if you want to output something to the response from the run you can and have a "to" the to needs to be of type include
+
+there is a difference between <to>null</to> and not specifying <to>, not specifying meand that the request will
+continue down the filter chain ie if the request was for x.jsp x.jsp will be run but if <to>null</to> was specified
+then the request will be ended
+
+
+
+missing link in web development for a long time has been the ability to filter the http request chain
+-->
+
+<!--
+
+Our extranet has recently converted from single role to multiple role,
+this potentially means hundreds of lines of code have to change. Is
+there an easier way?
+
+Pass around a new role id to all pages in a section without going to
+each page and for and adding a request parameter. Tabbed browsing so it
+can't be session based.
+
+We can add it to the URL then and write it in and out before and after
+the original code is run. This means no changes for the presentation
+layer only business logic needs to change.
+
+ < strip any role-id from a URL and save it as a request
+attribute >
+ <rule>
+ <from>^/for-people/(\d+)/.*$</from>
+ <set name="role_id">$1</set>
+ </rule>
+
+ < restore the role-id to the URL >
+ <outbound-rule>
+ <condition type="attribute" name="role_id"/>
+ <from>^/for-people/(.*)</from>
+ <to encode="true">/for-people/%{attribute:role_id}/$1</to>
+ </outbound-rule>
+
+
+eg, an imconing request for...
+/for-people/1223/home/
+
+urlrewritefilter will match the rule and run...
+request.setAttribute("role_id", 1223);
+
+the request will be forwarded to:
+/for-people/home/
+
+when JSP is being processed and response.encodeURL is called on each of
+the links the role id will be added back in
+
+ie, /for-people/home/ will be transalted back to
+/for-people/1223/home/
+
+///////////////////////////
+
+FAQ
+Cross context forwarding.
+ Servlet containers don't support it.
+
+
+-->
+
+<a name="urlabs"></a>
+
+<h2>URL Abstraction</h2>
+
+<p>Both incoming request and embedded links in JSP's can be rewritten allowing full URL abstraction.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/tidy/page$&lt;/from&gt;
+ &lt;to&gt;/old/url/scheme/page.jsp&lt;/to&gt;
+ &lt;/rule&gt;
+ &lt;outbound-rule&gt;
+ &lt;from&gt;^/old/url/scheme/page.jsp$&lt;/from&gt;
+ &lt;to&gt;/tidy/page&lt;/to&gt;
+ &lt;/outbound-rule&gt;
+</code></pre>
+
+<p>Any incoming requests for <code>/tidy/page</code> will be transparently forwarded to
+ <code>/old/url/scheme/page.jsp</code>.</p>
+
+<p>If you use JSTL your JSP page would have something like:</p>
+<pre><code>&lt;a href="&lt;c:url value="/old/url/scheme/page.jsp"/&gt;"&gt;some link&lt;/a&gt;</code></pre>
+
+<p>This will be rewritten upon output to:</p>
+<pre><code>&lt;a href="/tidy/page"&gt;some link&lt;/a&gt;</code></pre>
+
+<p>Or if you use standard JSP:</p>
+<pre><code>&lt;a href="&lt;%= response.encodeURL("/old/url/scheme/page.jsp") %>">some link&lt;/a></code></pre>
+
+<p>Will generate output like:</p>
+<pre><code>&lt;a href="/tidy/page">some link&lt;/a></code></pre>
+
+
+<a name="mod_re"></a>
+
+<h2>mod_rewrite vs urlrewrite filter</h2>
+
+
+<p>Examples of mod_rewrite style conf vs urlrewrite filter conf are below, there are all examples copied directly from
+ Apache 2.0's official <a href="http://httpd.apache.org/docs-2.0/misc/rewriteguide.html">rewrite guide</a>.</p>
+
+<pre><code>
+
+&lt;rule&gt;
+ &lt;name&gt;Canonical URLs&lt;/name&gt;
+ &lt;note&gt;
+ On some webservers there are more than one URL for a resource. Usually there are canonical URLs (which
+ should be actually used and distributed) and those which are just shortcuts, internal ones, etc. Independent
+ of which URL the user supplied with the request he should finally see the canonical one only.
+
+ We do an external HTTP redirect for all non-canonical URLs to fix them in the location view of the Browser
+ and for all subsequent requests. In the example ruleset below we replace /~user by the canonical /u/user and
+ fix a missing trailing slash for /u/user.
+
+ RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
+ RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]
+ &lt;/note&gt;
+ &lt;from&gt;^/~([^/]+)/?(.*)&lt;/from&gt;
+ &lt;to type="redirect"&gt;/u/$1/$2&lt;/to&gt;
+&lt;/rule&gt;
+&lt;rule&gt;
+ &lt;from&gt;^/([uge])/([^/]+)$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/$1/$2/&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Canonical Hostnames&lt;/name&gt;
+ &lt;note&gt;
+ The goal of this rule is to force the use of a particular hostname, in preference to other hostnames which
+ may be used to reach the same site. For example, if you wish to force the use of www.example.com instead of
+ example.com, you might use a variant of the following recipe.
+
+ RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
+ RewriteCond %{HTTP_HOST} !^$
+ RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]
+ &lt;/note&gt;
+ &lt;condition name="host" operator="notequal"&gt;^fully\.qualified\.domain\.name&lt;/condition&gt;
+ &lt;condition name="host" operator="notequal"&gt;^$&lt;/condition&gt;
+ &lt;from&gt;^/(.*)&lt;/from&gt;
+ &lt;to type="redirect" last="true"&gt;http://fully.qualified.domain.name/$1&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Moved DocumentRoot&lt;/name&gt;
+ &lt;note&gt;
+ Usually the DocumentRoot of the webserver directly relates to the URL "/". But often this data is not
+ really of top-level priority, it is perhaps just one entity of a lot of data pools. For instance at our
+ Intranet sites there are /e/www/ (the homepage for WWW), /e/sww/ (the homepage for the Intranet) etc. Now
+ because the data of the DocumentRoot stays at /e/www/ we had to make sure that all inlined images and other
+ stuff inside this data pool work for subsequent requests.
+
+ We just redirect the URL / to /e/www/. While is seems trivial it is actually trivial with mod_rewrite, only.
+ Because the typical old mechanisms of URL Aliases (as provides by mod_alias and friends) only used prefix
+ matching. With this you cannot do such a redirection because the DocumentRoot is a prefix of all URLs.
+ With mod_rewrite it is really trivial:
+
+ RewriteRule ^/$ /e/www/ [R]
+ &lt;/note&gt;
+ &lt;from&gt;^/$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/e/www/&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Trailing Slash Problem&lt;/name&gt;
+ &lt;note&gt;
+ Every webmaster can sing a song about the problem of the trailing slash on URLs referencing directories.
+ If they are missing, the server dumps an error, because if you say /~quux/foo instead of /~quux/foo/ then
+ the server searches for a file named foo. And because this file is a directory it complains. Actually it
+ tries to fix it itself in most of the cases, but sometimes this mechanism need to be emulated by you. For
+ instance after you have done a lot of complicated URL rewritings to CGI scripts etc.
+
+ The solution to this subtle problem is to let the server add the trailing slash automatically. To do this
+ correctly we have to use an external redirect, so the browser correctly requests subsequent images etc. If
+ we only did a internal rewrite, this would only work for the directory page, but would go wrong when any
+ images are included into this page with relative URLs, because the browser would request an in-lined object.
+ For instance, a request for image.gif in /~quux/foo/index.html would become /~quux/image.gif without the
+ external redirect!
+ &lt;/note&gt;
+ &lt;from&gt;^/~quux/foo$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/~quux/foo/&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Move Homedirs to Different Webserver&lt;/name&gt;
+ &lt;note&gt;
+ Many webmasters have asked for a solution to the following situation: They wanted to redirect just all
+ homedirs on a webserver to another webserver. They usually need such things when establishing a newer
+ webserver which will replace the old one over time.
+
+ The solution is trivial with mod_rewrite (and urlrewrite filter). On the old webserver we just redirect all
+ /~user/anypath URLs to http://newserver/~user/anypath.
+
+ RewriteRule ^/~(.+) http://newserver/~$1 [R,L]
+ &lt;/note&gt;
+ &lt;from&gt;^/~(.+)&lt;/from&gt;
+ &lt;to type="redirect" last="true"&gt;http://newserver/~$1&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Structured Homedirs&lt;/name&gt;
+ &lt;note&gt;
+ Some sites with thousands of users usually use a structured homedir layout, i.e. each homedir is in a
+ subdirectory which begins for instance with the first character of the username. So, /~foo/anypath is
+ /home/f/foo/.www/anypath while /~bar/anypath is /home/b/bar/.www/anypath.
+
+ We use the following ruleset to expand the tilde URLs into exactly the above layout.
+
+ RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/.www$3
+ &lt;/note&gt;
+ &lt;from&gt;^/~(([a-z])[a-z0-9]+)(.*)&lt;/from&gt;
+ &lt;to&gt;/home/$2/$1/.www$3&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Redirect Homedirs For Foreigners&lt;/name&gt;
+ &lt;note&gt;
+ We want to redirect homedir URLs to another webserver www.somewhere.com when the requesting user does not
+ stay in the local domain ourdomain.com. This is sometimes used in virtual host contexts.
+
+ Just a rewrite condition:
+
+ RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$
+ RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]
+ &lt;/note&gt;
+ &lt;condition name="host"&gt;!^.+\.ourdomain\.com$&lt;/condition&gt;
+ &lt;from&gt;^(/~.+)&lt;/from&gt;
+ &lt;to type="redirect" last="true"&gt;http://www.somewhere.com/$1&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Time-Dependent Rewriting&lt;/name&gt;
+ &lt;note&gt;
+ When tricks like time-dependent content should happen a lot of webmasters still use CGI scripts which do for
+ instance redirects to specialized pages. How can it be done via mod_rewrite?
+
+ There are a lot of types in conjunction with operators we can do time-dependent redirects:
+
+ RewriteCond %{TIME_HOUR}%{TIME_MIN} &gt;0700
+ RewriteCond %{TIME_HOUR}%{TIME_MIN} &lt;1900
+ RewriteRule ^foo\.html$ foo.day.html
+ RewriteRule ^foo\.html$ foo.night.html
+ &lt;/note&gt;
+ &lt;condition type="hourofday" operator="greater"&gt;7&lt;/condition&gt;
+ &lt;condition type="hourofday" operator="less"&gt;19&lt;/condition&gt;
+ &lt;from&gt;^foo\.html$&lt;/from&gt;
+ &lt;to&gt;foo.day.html&lt;/to&gt;
+&lt;/rule&gt;
+&lt;rule&gt;
+ &lt;from&gt;^foo\.html$&lt;/from&gt;
+ &lt;to&gt;foo.night.html&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;&lt;/name&gt;
+ &lt;note&gt;
+ Assume we have recently renamed the page foo.html to bar.html and now want to provide the old URL for
+ backward compatibility. Actually we want that users of the old URL even not recognize that the pages was
+ renamed.
+
+ We rewrite the old URL to the new one internally via the following rule:
+
+ RewriteBase /~quux/
+ RewriteRule ^foo\.html$ bar.html
+ &lt;/note&gt;
+ &lt;from&gt;^/~quux/foo\.html$&lt;/from&gt;
+ &lt;to&gt;/~quux/bar.html&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;From Old to New (extern)&lt;/name&gt;
+ &lt;note&gt;
+ Assume again that we have recently renamed the page foo.html to bar.html and now want to provide the old URL
+ for backward compatibility. But this time we want that the users of the old URL get hinted to the new one,
+ i.e. their browsers Location field should change, too.
+
+ We force a HTTP redirect to the new URL which leads to a change of the browsers and thus the users view:
+
+ RewriteBase /~quux/
+ RewriteRule ^foo\.html$ bar.html [R]
+ &lt;/note&gt;
+ &lt;from&gt;^/~quux/foo\.html$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/~quux/bar.html&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Browser Dependent Content&lt;/name&gt;
+ &lt;note&gt;
+ At least for important top-level pages it is sometimes necessary to provide the optimum of browser dependent
+ content, i.e. one has to provide a maximum version for the latest Netscape variants, a minimum version for
+ the Lynx browsers and a average feature version for all others.
+
+ We cannot use content negotiation because the browsers do not provide their type in that form. Instead we
+ have to act on the HTTP header "User-Agent". The following condig does the following: If the HTTP header
+ "User-Agent" begins with "Mozilla/3", the page foo.html is rewritten to foo.NS.html and and the rewriting
+ stops. If the browser is "Lynx" or "Mozilla" of version 1 or 2 the URL becomes foo.20.html. All other
+ browsers receive page foo.32.html. This is done by the following ruleset:
+
+ RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.*
+ RewriteRule ^foo\.html$ foo.NS.html [L]
+
+ RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR]
+ RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].*
+ RewriteRule ^foo\.html$ foo.20.html [L]
+
+ RewriteRule ^foo\.html$ foo.32.html [L]
+ &lt;/note&gt;
+ &lt;condition name="user-agent"&gt;^Mozilla/3.*&lt;/condition&gt;
+ &lt;from&gt;^foo\.html$&lt;/from&gt;
+ &lt;to last="true"&gt;foo.NS.html&lt;/to&gt;
+&lt;/rule&gt;
+&lt;rule&gt;
+ &lt;condition name="user-agent" next="or"&gt;^Lynx/.*&lt;/condition&gt;
+ &lt;condition name="user-agent"&gt;^Mozilla/[12].*&lt;/condition&gt;
+ &lt;from&gt;^foo\.html$&lt;/from&gt;
+ &lt;to last="true"&gt;foo.20.html&lt;/to&gt;
+&lt;/rule&gt;
+&lt;rule&gt;
+ &lt;from&gt;^foo\.html$&lt;/from&gt;
+ &lt;to last="true"&gt;foo.32.html&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;From Static to Dynamic&lt;/name&gt;
+ &lt;note&gt;
+ How can we transform a static page foo.html into a dynamic variant foo.cgi in a seamless way, i.e. without
+ notice by the browser/user.
+
+ We just rewrite the URL to the jsp/servlet and force the correct MIME-type so it gets really run as
+ a CGI-script. This way a request to /~quux/foo.html internally leads to the invocation of /~quux/foo.jsp.
+
+ RewriteBase /~quux/
+ RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]
+ &lt;/note&gt;
+ &lt;from&gt;^/~quux/foo\.html$&lt;/from&gt;
+ &lt;to&gt;/~quux/foo.jsp&lt;/to&gt;
+&lt;/rule&gt;
+
+&lt;rule&gt;
+ &lt;name&gt;Blocking of Robots&lt;/name&gt;
+ &lt;note&gt;
+ How can we block a really annoying robot from retrieving pages of a specific webarea? A /robots.txt file
+ containing entries of the "Robot Exclusion Protocol" is typically not enough to get rid of such a robot.
+
+ We use a ruleset which forbids the URLs of the webarea /~quux/foo/arc/ (perhaps a very deep directory
+ indexed area where the robot traversal would create big server load). We have to make sure that we forbid
+ access only to the particular robot, i.e. just forbidding the host where the robot runs is not enough.
+ This would block users from this host, too. We accomplish this by also matching the User-Agent HTTP header
+ information.
+
+ RewriteCond %{HTTP_USER_AGENT} ^NameOfBadRobot.*
+ RewriteCond %{REMOTE_ADDR} ^123\.45\.67\.[8-9]$
+ RewriteRule ^/~quux/foo/arc/.+ - [F]
+ &lt;/note&gt;
+ &lt;condition name="user-agent"&gt;^NameOfBadRobot.*&lt;/condition&gt;
+ &lt;condition type="remote-addr"&gt;^123\.45\.67\.[8-9]$&lt;/condition&gt;
+ &lt;from&gt;^/~quux/foo/arc/.+&lt;/from&gt;
+ &lt;set type="status"&gt;403&lt;/set&gt;
+ &lt;to&gt;null&lt;/to&gt;
+&lt;/rule&gt;
+
+
+&lt;rule&gt;
+ &lt;name&gt;Blocked Inline-Images&lt;/name&gt;
+ &lt;note&gt;
+ Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined GIF graphics. These graphics are
+ nice, so others directly incorporate them via hyperlinks to their pages. We don't like this practice because
+ it adds useless traffic to our server.
+
+ While we cannot 100% protect the images from inclusion, we can at least restrict the cases where the browser
+ sends a HTTP Referer header.
+
+ RewriteCond %{HTTP_REFERER} !^$
+ RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
+ RewriteRule .*\.gif$ - [F]
+ &lt;/note&gt;
+ &lt;condition name="referer" operator="notequal"&gt;^$&lt;/condition&gt;
+ &lt;condition name="referer" operator="notequal"&gt;^http://www.quux-corp.de/~quux/.*$&lt;/condition&gt;
+ &lt;from&gt;.*\.gif$&lt;/from&gt;
+ &lt;set type="status"&gt;403&lt;/set&gt;
+ &lt;to&gt;null&lt;/to&gt;
+&lt;/rule&gt;
+
+&lt;rule&gt;
+ &lt;name&gt;Blocked Inline-Images example 2&lt;/name&gt;
+ &lt;note&gt;
+ RewriteCond %{HTTP_REFERER} !^$
+ RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
+ RewriteRule ^inlined-in-foo\.gif$ - [F]
+ &lt;/note&gt;
+ &lt;condition name="referer" operator="notequal"&gt;^$&lt;/condition&gt;
+ &lt;condition name="referer" operator="notequal"&gt;.*/foo-with-gif\.html$&lt;/condition&gt;
+ &lt;from&gt;^inlined-in-foo\.gif$&lt;/from&gt;
+ &lt;set type="status"&gt;403&lt;/set&gt;
+ &lt;to&gt;null&lt;/to&gt;
+&lt;/rule&gt;
+
+</code></pre>
+
+
+
+</div>
+
+<div id="footer">
+Copyright Paul Tuckey <!--@year-->2010<!--/@year-->
+ - <a href="http://tuckey.org/urlrewrite/">UrlRewirteFilter</a>
+</div>
+
+</body>
+</html>
+
View
1,472 doc/urlrewritefilter/index.html
@@ -0,0 +1,1472 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
+<head>
+ <title>UrlRewriteFilter - Manual</title>
+ <style type="text/css">
+ @import url( "doc.css" );
+ </style>
+</head>
+
+<body>
+
+<div id="masthead">
+ <a href="http://tuckey.org/urlrewrite/">
+ <img id="logo" src="urf.gif" border="0" alt="Tuckey Logo" />
+ Url Rewrite Filter <!--@ver-->4.0.0<!--/@ver--></a>
+</div>
+
+<div id="menu">
+<ul>
+ <li><a href="http://tuckey.org/urlrewrite/">Home</a></li>
+ <li><a href="http://tuckey.org/urlrewrite/#download">Download</a></li>
+ <li><a href="http://code.google.com/p/urlrewritefilter/source">svn access</a></li>
+ <li><a href="http://groups.google.com/group/urlrewrite">UrlRewrite google group</a><br/>&nbsp;</li>
+
+ <li><a href="introduction.html">Background</a>
+ <ul>
+ <li><a href="introduction.html#license">License</a></li>
+ <li><a href="introduction.html#changelog">Changelog</a></li>
+ </ul>
+ </li>
+ <li><b>Configuration</b>
+ <ul>
+ <li><a href="#install">Install</a></li>
+ <li><a href="#tips">Tips</a></li>
+ <li><a href="#filterparams">Filter Parameters</a></li>
+ <li><a href="#configuration">Configuration File</a></li>
+ <li><a href="#anttask">Ant Task</a></li>
+ <li><a href="index.html#mod_rewrite_conf">mod_rewrite Style</a></li>
+ </ul>
+ </li>
+ <li><a href="annotation.html">Annotations</a></li>
+ <li><a href="guide.html">Examples</a>
+ <ul>
+ <li><a href="guide.html#method">Method Invocation</a></li>
+ <li><a href="guide.html#urlabs">URL Abstraction</a></li>
+ <li><a href="guide.html#mod_re">mod_rewrite vs UrlRewriteFilter</a></li>
+ </ul>
+ </li>
+</ul>
+</div>
+
+<div id="main">
+
+ <h1>Manual</h1>
+
+
+<p>Community support is available at <a href="http://groups.google.com/group/urlrewrite">urlrewrite google group</a>.</p>
+
+<p>Read <b><a href="guide.html">examples of usage</a></b> and a
+ <a href="urlrewrite-conf-overview-sample.html">sample</a> of the <a href="#anttask">ant task</a> report.
+ If you have feedback, or conf you want to share with the world <a href="mailto:paul@tuckey.org">email me</a>.
+ If you have any suggestions/examples for this manual please post them to the
+ <a href="http://groups.google.com/group/urlrewrite">group</a>.</p>
+
+
+<a name="install"> </a>
+<h2>Install</h2>
+
+<ol>
+ <li><a href="http://tuckey.org/urlrewrite/#download">Download</a> the zip (or tar.gz) and extract it into your
+ context's directory ie, so that urlrewrite.xml goes into the WEB-INF directory.</li>
+ <li>Add the following to your WEB-INF/web.xml (add it near the top above your
+ servlet mappings (if you have any)): (see <a href="http://tuckey.org/urlrewrite/manual/3.0/#filterparams">filter
+ parameters</a> for more options)
+ <pre><code>
+ &lt;filter&gt;
+ &lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;
+ &lt;filter-class&gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&lt;/filter-class&gt;
+ &lt;/filter&gt;
+ &lt;filter-mapping&gt;
+ &lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;
+ &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
+ &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;
+ &lt;/filter-mapping&gt;
+ </code></pre></li>
+ <li>Add your own configuration to the WEB-INF/urlrewrite.xml that was created.</li>
+ <li>Restart the context.</li>
+</ol>
+
+<p>You can visit <a href="http://127.0.0.1:8080/rewrite-status">http://127.0.0.1:8080/rewrite-status</a>
+ (or whatever the address of your local webapp and context)
+ to see output (note: this page is only viewable from localhost).</p>
+
+
+<a name="filterparams"> </a>
+<h2>Filter Parameters</h2>
+
+<p>There are a few advanced filter parameters for enabling conf file reloading etc. There are self-explanatory.</p>
+
+<pre><code>
+ &lt;filter&gt;
+ &lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;
+ &lt;filter-class&gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&lt;/filter-class&gt;
+
+ &lt;!-- set the amount of seconds the conf file will be checked for reload
+ can be a valid integer (0 denotes check every time,
+ -1 denotes no reload check, default -1) --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>confReloadCheckInterval</b>&lt;/param-name&gt;
+ &lt;param-value&gt;60&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- if you need to the conf file path can be changed
+ it is specified as a path relative to the root of your context
+ (default /WEB-INF/urlrewrite.xml) --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>confPath</b>&lt;/param-name&gt;
+ &lt;param-value&gt;/WEB-INF/urlrewrite.xml&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- sets up log level (will be logged to context log)
+ can be: TRACE, DEBUG, INFO (default), WARN, ERROR, FATAL, log4j, commons, slf4j,
+ sysout:{level} (ie, sysout:DEBUG)
+ if you are having trouble using normal levels use sysout:DEBUG
+ (default WARN) --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>logLevel</b>&lt;/param-name&gt;
+ &lt;param-value&gt;DEBUG&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- you can change status path so that it does not
+ conflict with your installed apps (note, defaults
+ to /rewrite-status) note, must start with / --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>statusPath</b>&lt;/param-name&gt;
+ &lt;param-value&gt;/status&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- you can disable status page if desired
+ can be: true, false (default true) --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>statusEnabled</b>&lt;/param-name&gt;
+ &lt;param-value&gt;true&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- you may want to allow more hosts to look at the status page
+ statusEnabledOnHosts is a comma delimited list of hosts, * can
+ be used as a wildcard (defaults to "localhost, local, 127.0.0.1") --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>statusEnabledOnHosts</b>&lt;/param-name&gt;
+ &lt;param-value&gt;localhost, dev.*.myco.com, *.uat.mycom.com&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- you may want to allow more hosts to look at the status page
+ statusEnabledOnHosts is a comma delimited list of hosts, * can
+ be used as a wildcard (defaults to "localhost, local, 127.0.0.1") --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>statusEnabledOnHosts</b>&lt;/param-name&gt;
+ &lt;param-value&gt;localhost, dev.*.myco.com, *.uat.mycom.com&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- defaults to false. use mod_rewrite style configuration file (if this is true and confPath
+ is not specified confPath will be set to /WEB-INF/.htaccess) --&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>modRewriteConf</b>&lt;/param-name&gt;
+ &lt;param-value&gt;false&lt;/param-value&gt;
+ &lt;/init-param&gt;
+
+ &lt;!-- load mod_rewrite style configuration from this parameter's value.
+ note, Setting this parameter will mean that all other conf parameters are ignored.
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>modRewriteConfText</b>&lt;/param-name&gt;
+ &lt;param-value&gt;
+ RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2 [R]
+ RewriteRule ^/([uge])/([^/]+)$ /$1/$2/ [R]
+ &lt;/param-value&gt;
+ &lt;/init-param&gt;
+ --&gt;
+
+ &lt;!-- defaults to false. allow conf file to be set by calling /rewrite-status/?conf=/WEB-INF/urlrewrite2.xml
+ designed to be used for testing only
+ &lt;init-param&gt;
+ &lt;param-name&gt;<b>allowConfSwapViaHttp</b>&lt;/param-name&gt;
+ &lt;param-value&gt;false&lt;/param-value&gt;
+ &lt;/init-param&gt;
+ --&gt;
+
+ &lt;/filter&gt;
+
+ &lt;filter-mapping&gt;
+ &lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;
+ &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
+ &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;
+ &lt;/filter-mapping&gt;
+</code></pre>
+
+<p>Note, setting <code>logLevel</code> to <code>log4j</code> or <code>commons</code> will cause the built in loging to
+ call either <a href="http://logging.apache.org/log4j/docs/index.html">log4j</a> or
+ <a href="http://jakarta.apache.org/commons/logging/">commons-logging</a> as if they were the logging framework,
+ obviously you will need to have the jar for log4j or commons-logging in your classpath.</p>
+
+
+<a name="configuration"> </a>
+<h2>Configuration File WEB-INF/urlrewrite.xml</h2>
+
+<table align="right">
+ <tr>
+ <td>
+ <small>
+ <a href="#urlrewrite">&lt;urlrewrite&gt;</a> &nbsp;
+ <a href="#rule">&lt;rule&gt;</a> &nbsp;
+ <a href="#outbound-rule">&lt;outbound-rule&gt;</a> &nbsp;
+ <a href="#class-rule">&lt;class-rule&gt;</a>
+ <br/>
+ <a href="#name">&lt;name&gt;</a> &nbsp;
+ <a href="#note">&lt;note&gt;</a> &nbsp;
+ <a href="#condition">&lt;condition&gt;</a> &nbsp;
+ <a href="#from">&lt;from&gt;</a> &nbsp;
+ <a href="#to">&lt;to&gt;</a> &nbsp;
+ <a href="#set">&lt;set&gt;</a> &nbsp;
+ <a href="#run">&lt;run&gt;</a> &nbsp;
+ <br/>
+ <a href="#backreferences">Back References</a> &nbsp;
+ <a href="#variables">Variables</a> &nbsp;
+ <a href="#functions">Functions</a> &nbsp;
+ </small>
+ </td>
+ </tr>
+</table>
+<br clear="all"/>
+
+<p>Configuration is done via a simple XML file that lives in your <code>WEB-INF</code> folder. It should be named
+ urlrewrite.xml.
+ It may be helpful to read the <a href="http://tuckey.org/res/dtds/urlrewrite3.0.dtd">UrlRewriteFilter DTD
+ (Document Type Definition)</a>. Please also make sure you look at the <a href="guide.html">examples</a>. A simple
+ configuration file looks like:</p>
+
+<pre><code>
+ &lt;?xml version="1.0" encoding="utf-8"?&gt;
+
+ &lt;!DOCTYPE urlrewrite
+ PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
+ "http://tuckey.org/res/dtds/urlrewrite3.0.dtd"&gt;
+
+ &lt;urlrewrite&gt;
+
+ &lt;rule&gt;
+ &lt;from&gt;^/some/olddir/(.*)$&lt;/from&gt;
+ &lt;to type="redirect"&gt;/very/newdir/$1&lt;/to&gt;
+ &lt;/rule&gt;
+
+ &lt;rule match-type="wildcard"&gt;
+ &lt;from&gt;/blog/archive/**&lt;/from&gt;
+ &lt;to type="redirect"&gt;/roller/history/$1&lt;/to&gt;
+ &lt;/rule&gt;
+
+ &lt;/urlrewrite&gt;
+</code></pre>
+
+
+<p>The urlrewrite.xml file must have a root element called "urlrewrite" and must contain
+ at least one "rule" element.</p>
+
+<p>A "rule" must contain a "from" and a "to", and can have zero or more "condition" elements and zero or more and/or
+ "set" elements.</p>
+
+<p>When a "rule" is processed against an incoming request, all the "condition" elements must be met, then
+ the "from" will be applied to the request URL and the final URL generated by applying the
+ "to" to the "from" pattern. So long as the rule has matched then the "set" will be run.</p>
+
+
+
+<p>When executing a rule the filter will (very simplified) loop over all rules and for each do something like this psuedo code:</p>
+
+<pre><code>
+ Pattern.compile(&lt;from&gt; element);
+ pattern.matcher(request url);
+ matcher.replaceAll(&lt;to&gt; element);
+ if ( &lt;condition&gt; elements match && matcher.find() ) {
+ handle &lt;set&gt; elements (if any)
+ execute &lt;run&gt; elements (if any)
+ perform &lt;to&gt; element (if any)
+ }
+</code></pre>
+
+
+<a name="urlrewrite"> </a>
+<h3>&lt;urlrewrite&gt; element</h3>
+
+<p>The top level element.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="2">default-match-type <br/><small>(optional)</small></td>
+ <td><b>regex</b> (default)</td>
+ <td>All rules and thier conditions will be processed using the Java Regular Expression engine (unless
+ <code>match-type</code> is specified on a rule).</td>
+ </tr>
+ <tr>
+ <td>wildcard</td>
+ <td>All rules and thier conditions will be processed using the <a href="#wildcard">Wildcard Expression
+ engine</a>
+ (unless <code>match-type</code> is specified on a rule).</td>
+ </tr>
+ <tr>
+ <td rowspan="5">decode-using <br/><small>(optional)</small></td>
+ <td><b>header,utf8</b> (default)</td>
+ <td>When URL is decoded request.getCharacterEncoding() will be used, if that is empty UTF-8 will be used.
+ </td>
+ </tr>
+ <tr>
+ <td>null</td>
+ <td>Do not decode at all. (note, this means the literal string null e.g. decode-using="null") </td>
+ </tr>
+ <tr>
+ <td>header</td>
+ <td>Only use request.getCharacterEncoding() to decode.</td>
+ </tr>
+ <tr>
+ <td>[encoding]</td>
+ <td>Only use a specific character encoding eg, ISO-8859-1.
+ See <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Java Charset Object</a>
+ for all character encodings.
+ </td>
+ </tr>
+ <tr>
+ <td>header,[encoding]</td>
+ <td>
+ When URL is decoded request.getCharacterEncoding() will be used, if that is empty a specific character
+ encoding eg, ISO-8859-1.
+ See <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Java Charset Object</a>
+ for all character encodings.
+ </td>
+ </tr>
+
+ <tr>
+ <td rowspan="2">use-query-string <br/><small>(optional)</small></td>
+ <td><b>false</b> (default)</td>
+ <td>The query string will <em>not</em> be appended to the url that the "from" element matches against.</td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>The query string will be appended to the url that the "from" element matches against.</td>
+ </tr>
+
+ <tr>
+ <td rowspan="2">use-context <br/><small>(optional)</small></td>
+ <td><b>false</b> (default)</td>
+ <td>The context path will <em>not</em> be added to the url that the "from" element matches against.</td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>The context path will be added to the url that the "from" element matches against.</td>
+ </tr>
+
+</table>
+
+
+<a name="rule"> </a>
+<h3>&lt;rule&gt; element</h3>
+
+<p>Zero or more. The basis of a rule.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="2">enabled <br/><small>(optional)</small></td>
+ <td><b>true</b> (default)</td>
+ <td>Enable this rule.</td>
+ </tr>
+ <tr>
+ <td><b>false</b></td>
+ <td>Disable this rule.</td>
+ </tr>
+ <tr>
+ <td rowspan="36">match-type <br/><small>(optional)</small></td>
+ <td><b>regex</b> (default)</td>
+ <td>This rule and it's conditions will be processed using the Java Regular Expression engine.</td>
+ </tr>
+ <tr>
+ <td><b>wildcard</b></td>
+ <td>This rule and it's conditions will be processed using the <a href="#wildcard">Wildcard Expression engine</a>.
+ </td>
+ </tr>
+</table>
+
+<p>In the following example requests for <code>/world/usa/nyc</code> will be transparently forwarded to
+ <code>/world.jsp</code></p>
+
+<pre><code>
+ &lt;rule match-type="regex"&gt;
+ &lt;from&gt;^/world/([a-z]+)/([a-z]+)$&lt;/from&gt;
+ &lt;to&gt;/world.jsp&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<pre><code>
+ &lt;rule match-type="wildcard"&gt;
+ &lt;from&gt;/world/*/*&lt;/from&gt;
+ &lt;to&gt;/world.jsp&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<a name="outbound-rule"> </a>
+<h3>&lt;outbound-rule&gt; element</h3>
+
+<p>Zero or more. This is very similar to a normal rule but it is used for rewriting urls that go through
+ <code>response.encodeURL()</code>.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="2">enabled <br/><small>(optional)</small></td>
+ <td><b>true</b> (default)</td>
+ <td>Enable this rule.</td>
+ </tr>
+ <tr>
+ <td>false</td>
+ <td>Disable this rule.</td>
+ </tr>
+ <tr>
+ <td rowspan="2">encodefirst <br/><small>(optional)</small></td>
+ <td><b>false</b> (default)</td>
+ <td>Run encodeURL() <b>after</b> running this outbound rule.</td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>Run encodeURL() <b>before</b> running this outbound rule.</td>
+ </tr>
+
+</table>
+
+<p>May contain "run", "from", "to" and "set" element(s) also. Example:</p>
+
+<pre><code>
+ &lt;outbound-rule&gt;
+ &lt;from&gt;^/world.jsp?country=([a-z]+)&amp;amp;city=([a-z]+)$&lt;/from&gt;
+ &lt;to&gt;/world/$1/$2&lt;/to&gt;
+ &lt;/outbound-rule&gt;
+</code></pre>
+
+<p>Using the example above JSP's with the code
+ <br/><code>&lt;a href="&lt;%= response.encodeURL("/world.jsp?country=usa&amp;amp;city=nyc")
+ %&gt;"&gt;nyc&lt;/a&gt;</code>
+ <br/>will output
+ <br/><code>&lt;a href="/world/usa/nyc"&gt;nyc&lt;/a&gt;</code>
+</p>
+
+<p>Or JSTL
+ <br/><code>&lt;a href="&lt;c:url value="/world.jsp?country=${country}&amp;amp;city=${city}"
+ /&gt;"&gt;nyc&lt;/a&gt;</code>
+ <br/>will output
+ <br/><code>&lt;a href="/world/usa/nyc"&gt;nyc&lt;/a&gt;</code>
+</p>
+
+<p>Note, If you are using JSTL (ie, &lt;c:url) this will work also.</p>
+
+
+<a name="name"> </a>
+<h3>&lt;name&gt; element</h3>
+
+<p>An optional element used for documenting the name of the rule. This can be used with rule and outbound-rule.
+ See <a href="#anttask">ant task</a>.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ <b>&lt;name&gt;World Rule&lt;/name&gt;</b>
+ &lt;from&gt;^/world/([a-z]+)/([a-z]+)$&lt;/from&gt;
+ &lt;to&gt;/world.jsp?country=$1&amp;amp;city=$2&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<a name="note"> </a>
+<h3>&lt;note&gt; element</h3>
+
+<p>A simple optional element used for documentation of the rule. This can be used with rule and outbound-rule.
+ See <a href="#anttask">ant task</a>.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;name&gt;World Rule&lt;/name&gt;
+ <b>&lt;note&gt;
+ Cleanly redirect world requests to JSP,
+ a country and city must be specified.
+ &lt;/note&gt;</b>
+ &lt;from&gt;^/world/([a-z]+)/([a-z]+)$&lt;/from&gt;
+ &lt;to&gt;/world.jsp&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+
+<a name="condition"> </a>
+<h3>&lt;condition&gt; element</h3>
+
+<p>An element that lets you choose condtions for the rule. Note, all conditions must be met for the rule to be run
+ (unless "next" is set to "or" obvoiusly).</p>
+
+<p>Value can be any <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html">Regular Expression</a>.</p>
+
+<table cellspacing="0">
+<tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+</tr>
+<tr>
+ <td rowspan="36">type <br/><small>(optional)</small></td>
+ <td><b>header</b> (default)</td><td>If used, the header name must be specified in the "name" attribute.</td></tr>
+
+<tr><td>method</td><td>The method of the request. GET, POST, HEAD etc.</td></tr>
+
+<tr><td>port</td><td>The port that the web application server is running on.</td></tr>
+
+<tr><td>time</td><td>
+ Current time at the server (this will be the number of seconds since 00:00:00 1970-01-01 UTC otherwise known as unix
+ time).
+ <br/>i.e. <code>(new Date()).getTime()</code>
+ <br/>This can be used for making sure content goes live only at a time you set.
+</td></tr>
+
+<tr><td>year</td><td>
+ Current year at the server.
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#YEAR">YEAR</a>)</code>
+</td></tr>
+
+<tr><td>month</td><td>
+ Month at the server. January is 0
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#MONTH">MONTH</a>)</code>
+</td></tr>
+<tr><td>dayofmonth</td><td>
+ Day of the month at the server. March first is 1
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#DAY_OF_MONTH">DAY_OF_MONTH</a>)</code>
+</td></tr>
+<tr><td>dayofweek</td><td>
+ Day of the week at the server. Saturday is 1, Sunday is 7
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#DAY_OF_WEEK">DAY_OF_WEEK</a>)</code>
+</td></tr>
+<tr><td>ampm</td><td>
+ AM or PM time at the server.
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#AM_PM">AM_PM</a>)</code>
+</td></tr>
+<tr><td>hourofday</td><td>
+ The hour of the day (24 hour clock) at the server. 10pm is 22
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#HOUR_OF_DAY">HOUR_OF_DAY</a>)</code>
+</td></tr>
+<tr><td>minute</td><td>
+ The minute field of the current time at the server.
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#MINUTE">MINUTE</a>)</code>
+</td></tr>
+<tr><td>second</td><td>
+ The second field of the current time at the server.
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#SECOND">SECOND</a>)</code>
+</td></tr>
+<tr><td>millisecond</td><td>
+ The millisecond field of the current time at the server.
+ <br/>i.e. <code>(Calendar.getInstance()).get(Calendar.<a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#MILLISECOND">MILLISECOND</a>)</code>
+</td></tr>
+
+<tr><td>attribute</td><td>
+ Will check the value of a request attribute (don't confuse this with parameter!), <code>name</code> must be set when
+ using this type.
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getAttribute(java.lang.String)">getAttribute</a>([name])
+</code>
+</td></tr>
+
+<tr><td>auth-type</td><td>
+ Will check the value of a request attribute (don't confuse this with parameter!)
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getAuthType()">getAuthType</a>()
+</code>
+</td></tr>
+
+<tr><td>character-encoding</td><td>
+ The character encoding of the imcoming request.
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getCharacterEncoding()">getCharacterEncoding</a>()
+</code>
+</td></tr>
+
+<tr><td>content-length</td><td>
+ The length of the imcoming request (can be useful if you want to deny large requests).
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getContentLength()">getContentLength</a>()
+</code>
+</td></tr>
+
+<tr><td>content-type</td><td>
+ The type of the imcoming request. (this is probably not that useful)
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getContentType()">getContentType</a>()
+</code>
+</td></tr>
+
+<tr><td>context-path</td><td>
+ The context path of the imcoming request.
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getContextPath()">getContextPath</a>()
+</code>
+</td></tr>
+
+<tr><td>cookie</td><td>
+ The value of a cookie, note, <code>name</code> must be specified to use this
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getCookies()">getCookies</a>()
+</code> the find we the one with [name] specified and check the value.
+</td></tr>
+
+<tr><td>parameter</td><td>
+ A tidier way of checking request parameters than looking for them in the query string. This will check for the
+ parameter in GET or POST, note, <code>name</code> must be specified.
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getParameter(java.lang.String)">getParameter</a>([name])
+</code>
+</td></tr>
+
+<tr><td>path-info</td><td>
+ i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getPathInfo()">getPathInfo</a>()
+</code>
+</td></tr>
+
+<tr><td>path-translated</td><td>
+ i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getPathTranslated()">getPathTranslated</a>()
+</code>
+</td></tr>
+
+<tr><td>protocol</td><td>The protocol used to make the request, e.g. HTTP/1.1
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getProtocol()">getProtocol</a>()
+</code>
+</td></tr>
+
+<tr><td>query-string</td><td>The query string used to make the request (if any), e.g. id=2345&name=bob
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getQueryString()">getQueryString</a>()
+</code>
+</td></tr>
+
+<tr><td>remote-addr</td><td>The IP address of the host making the request, e.g. 123.123.123.12
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getRemoteAddr()">getRemoteAddr</a>()
+</code>
+</td></tr>
+
+<tr><td>remote-host</td><td>The host name of the host making the request, e.g. 123qw-dsl.att.com (note,
+ this will only work if your app server is configured to lookup host names, most aren't).
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getRemoteHost()">getRemoteHost</a>()
+</code>
+</td></tr>
+
+<tr><td>remote-user</td><td>The login of the user making this request, if the user has been authenticated, e.g. bobt
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getRemoteUser()">getRemoteUser</a>()
+</code>
+</td></tr>
+
+<tr><td>requested-session-id</td><td>Returns the session ID specified by the client, e.g. 2344asd234sada4
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getRequestedSessionId()">getRequestedSessionId</a>()
+</code>
+</td></tr>
+
+<tr><td>requested-session-id-from-cookie</td><td>Whether the requested session ID is from a cookie or not
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#isRequestedSessionIdFromCookie()">isRequestedSessionIdFromCookie</a>()
+</code>
+</td></tr>
+
+<tr><td>requested-session-id-from-url</td><td>Whether the requested session ID is from the URL or not
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#isRequestedSessionIdFromURL()">isRequestedSessionIdFromURL</a>()
+</code>
+</td></tr>
+
+<tr><td>requested-session-id-valid</td><td>Whether the requested session ID is valid or not
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#isRequestedSessionIdValid()">isRequestedSessionIdValid</a>()
+</code>
+</td></tr>
+
+<tr><td>request-uri</td><td>Returns the part of this request's URL from the protocol name up to the query
+ string in the first line of the HTTP request
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getRequestURI()">getRequestURI()</a>
+</code>
+</td></tr>
+
+<tr><td>request-url</td><td>Reconstructs the URL the client used to make the request. The returned URL
+ contains a protocol, server name, port number, and server path, but it does not include query string parameters.
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getRequestURL()">getRequestURL()</a>
+</code>
+</td></tr>
+
+<tr><td>session-attribute</td><td>
+ (note, name must be set)
+ <br/>i.e. <code>session.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpSession.html#getAttribute(java.lang.String)">getAttribute([name])</a>
+</code>
+</td></tr>
+
+<tr><td>session-isnew</td><td>
+ Weather the session is new or not.
+ <br/>i.e. <code>session.<a href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpSession.html#isNew()">isNew()</a>
+</code>
+</td></tr>
+
+<tr><td>server-name</td><td>
+ The host name of the server to which the request was sent (from the host header not the machine name).
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getServerName()">getServerName()</a>
+</code>
+</td></tr>
+
+<tr><td>scheme</td><td>
+ The scheme used for the request, e.g. http or https
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#getScheme()">getScheme()</a>
+</code>
+</td></tr>
+
+<tr><td>user-in-role</td><td>
+ (Note, the value for this cannot be a regular expression)
+ <br/>i.e. <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#isUserInRole(java.lang.String)">isUserInRole([value])</a>
+</code>
+</td></tr>
+
+
+<tr>
+ <td>name <br/><small>(optional)</small></td>
+ <td>(can be anything)</td>
+ <td>If type is header, this specifies the name of the HTTP header used to run the value
+ against.</td>
+</tr>
+
+
+<tr>
+ <td rowspan="2">next <br/><small>(optional)</small></td>
+ <td><b>and</b> (default)</td><td>The next "rule" <b>and</b> this "rule" must match.</td></tr>
+<tr><td>or</td><td>The next "rule" <b>or</b> this "condition" may match.</td></tr>
+
+
+<tr>
+ <td rowspan="6">operator <br/><small>(optional)</small></td>
+ <td><b>equal</b> (default)</td>
+ <td>Equals. The operator to be used when the condition is run, the regular expression matches or the values are
+ equal.</td></tr>
+<tr><td>notequal</td><td>Not equal to. (i.e. request value != condition value). Note, this operator only work with
+ numeric rule types.</td></tr>
+<tr><td>greater</td><td>Greater than. (i.e. request value &gt; condition value). Note, this operator only work with
+ numeric
+ rule types.</td></tr>
+<tr><td>less</td><td>Less than. (i.e. request value &lt; condition value). Note, this operator only work with numeric
+ rule types.</td></tr>
+<tr><td>greaterorequal</td><td>Greater to or equal to. (i.e. request value &gt;= condition value). Note, this operator
+ only
+ work with numeric rule types.</td></tr>
+<tr><td>lessorequal</td><td>Less than or equal to. (i.e. request value &lt;= condition value). Note, this operator only
+ work with numeric rule types.</td></tr>
+</table>
+
+<p>Examples:</p>
+
+<pre><code>
+ &lt;condition name="user-agent" operator="notequal"&gt;Mozilla/[1-4]&lt;/condition&gt;
+
+ &lt;condition type="user-in-role" operator="notequal"&gt;bigboss&lt;/condition&gt;
+
+ &lt;condition name="host" operator="notequal"&gt;www.example.com&lt;/condition&gt;
+
+ &lt;condition type="method" next="or"&gt;PROPFIND&lt;/condition&gt;
+ &lt;condition type="method"&gt;PUT&lt;/condition&gt;
+</code></pre>
+
+
+ <a name="from"> </a>
+<h3>&lt;from&gt; element</h3>
+
+<p>You must always have exactly one from for each rule or outbound-rule. Value can be a regular expression in the
+ Perl5 style. Note, from url's are relative to the context.</p>
+
+<table>
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="2">casesensitive <br/><small>(optional)</small></td>
+ <td>false (default)</td>
+ <td>This value will be matched using case insentitive match. ie, "/WellingtoN" will match "/wellington".
+ </td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>This value will be matched using case sentitive match. ie, "/aAa" will NOT match "/aaa".
+ </td>
+ </tr>
+</table>
+
+<p>Example:</p>
+
+<pre><code>
+ &lt;from&gt;^/world/([a-z]+)$&lt;/from&gt;
+</code></pre>
+
+<a name="to"> </a>
+<h3>&lt;to&gt; element</h3>
+
+<p>Value can be a regular replacement expression in the Perl5 style.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="8">type <br/><small>(optional)</small></td>
+ <td>forward (default)</td>
+ <td>Requests matching the "conditions" for this "rule", and the URL in the "from" element will be internally
+ forwarded
+ to the URL specified in the "to" element. Note: In this case the "to" URL must be in the same context as
+ UrlRewriteFilter. This is the same as doing:
+ <br/><code>RequestDispatcher rq = request.getRequestDispatcher([to value]);
+ <br/>rq.forward(request, response);</code>
+ </td>
+ </tr>
+ <tr>
+ <td>passthrough</td>
+ <td>Identical to "forward".</td>
+ </tr>
+ <tr>
+ <td>redirect</td>
+ <td>Requests matching the "conditions" and the "from" for this rule will be HTTP redirected.
+ This is the same a doing:
+ <br/><code>HttpServletResponse.sendRedirect([to value]))</code></td>
+ </tr>
+ <tr>
+ <td>permanent-redirect</td>
+ <td>The same as doing:
+ <br/><code>response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ <br/>response.setHeader("Location", [to value]);</code>
+ <br/>(note, SC_MOVED_PERMANENTLY is HTTP status code 301)</td>
+ </tr>
+ <tr>
+ <td>temporary-redirect</td>
+ <td>The same as doing:
+ <br/><code>response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
+ <br/>response.setHeader("Location", [to value]);</code>
+ <br/>(note, SC_MOVED_TEMPORARILY is HTTP status code 302)</td>
+ </tr>
+ <tr>
+ <td>pre-include</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td>post-include</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td>proxy</td>
+ <td>The request will be proxied to the full url specified. commons-http and commons-codec must both be in the
+ classpath to use this feature.
+ </td>
+ </tr>
+ <tr>
+ <td rowspan="2">last <br/><small>(optional)</small></td>
+ <td>false (default)</td>
+ <td>The rest of the "rules" will be processed if this one succeeds.</td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>No more "rules" will be processed if this one is a match.</td>
+ </tr>
+ <tr>
+ <td rowspan="2">encode <br/><small>(optional)</small></td>
+ <td>false (default if under rule)</td>
+ <td>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletResponse.html#encodeURL(java.lang.String)">encodeURL</a>([to])
+ will be run on the to url before performing the rewrite.</td>
+ </tr>
+ <tr>
+ <td>true (default if under outbound-rule)</td>
+ <td>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletResponse.html#encodeURL(java.lang.String)">encodeURL</a>([to])
+ will NOT be called.</td>
+ </tr>
+ <tr>
+ <td>context <br/><small>(optional)</small></td>
+ <td> </td>
+ <td>If your application server is configured to allow "cross context" communication then this attribute can be used
+ to forward (and only forward, not redirect or other "to" types) requests to a named servlet context.
+ <br/>
+ <br/>On Tomcat, for instance, the application contexts in the server configuration (server.xml or
+ context.xml) need the option crossContext="true". For instance, the two applications mentioned before
+ ("app" and "forum") have to be defined as:
+ <br/>
+ <br/><code>&lt;Context docBase="app" path="/app" reloadable="true" crossContext="true"/&gt;</code>
+ <br/><code>&lt;Context docBase="forum" path="/forum" reloadable="true" crossContext="true"/&gt;</code>
+ </td>
+ </tr>
+ <tr>
+ <td rowspan="2">qsappend <br/><small>(optional)</small></td>
+ <td>false (default)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>Append the query string to the to url when redirecting or forwarding.</td>
+ </tr>
+</table>
+
+<p>Note, "to" can be null ie, <code>&lt;to&gt;null&lt;/to&gt;</code>, this will mean that the request will go no
+ further if the rule is matched (ie, this filter will not call <code>chain.doFilter</code>).</p>
+
+<p>If "to" is set to -, no substitution will take place and the request will go on like nothing happened (ie, this filter will call <code>chain.doFilter</code>).</p>
+
+<pre><code>
+ &lt;to&gt;/world.jsp?country=$1&lt;/to&gt;
+</code></pre>
+
+<p>To elements can contain backreferences and variables.</p>
+
+<a name="backreferences"> </a>
+<h4>Backreferences</h4>
+
+<pre><code>
+ %N
+</code></pre>
+
+<p>Provides access to the grouped parts (parentheses) of the pattern from the last matched <a href="#condition">Condition</a>
+ in the current rule.
+ N must be less than 10 and greater than 0 (i.e. %1, %2, %3 etc).</p>
+
+<a name="variables"> </a>
+<h4>Variables</h4>
+
+<pre><code>
+ %{VARIABLE-NAME}
+</code></pre>
+
+<p>Any valid condition type can be used as a variable name. ie,
+ '<code>%{port}</code>' will be translated to '<code>80</code>',
+ '<code>%{year}</code>' to '<code>2005</code>',
+ '<code>%{cookie:myCookie}</code>' would be translated to
+ '<code>myCookieValue</code>' (assuming the user had a cookie named myCookie with the value myCookieValue).</p>
+
+<p>Valid types are condition types, see <a href="#condition">condition</a> for a full description.</p>
+
+<a name="functions"> </a>
+<h4>Functions</h4>
+
+<pre><code>
+ ${FUNCTION:PARAMS}
+</code></pre>
+
+ <p>Functions can be places in <code>set</code> and <code>to</code> elements.</p>
+
+<table>
+ <tr>
+ <th>Name</th>
+ <th>Example</th>
+ <th>Example Returns</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td>replace</td>
+ <td><code>${replace:my cat is a blue cat:cat:dog}</code></td>
+ <td>my dog is a blue dog</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>replaceFirst</td>
+ <td><code>${replaceFirst:my cat is a blue cat:cat:dog}</code></td>
+ <td>my cat is a blue dog</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>escape</td>
+ <td><code>${escape:utf8:a b c}</code></td>
+ <td>a+b+c</td>
+ <td>Escapes/Encodes string using URLEncoder.encode using the specified encoding.</td>
+ </tr>
+ <tr>
+ <td>unescape</td>
+ <td><code>${unescape:utf8:a+b+c}</code></td>
+ <td>a b c</td>
+ <td>Unescapes/Unencodes string using URLEncoder.decode using the specified encoding.</td>
+ </tr>
+ <tr>
+ <td>lower</td>
+ <td><code>${lower:Hello World}</code></td>
+ <td>hello world</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>upper</td>
+ <td><code>${upper:hello}</code></td>
+ <td>HELLO</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>trim</td>
+ <td><code>${trim: abc def }</code></td>
+ <td>abc def</td>
+ <td></td>
+ </tr>
+ </table>
+
+
+<a name="set"> </a>
+<h3>&lt;set&gt; element</h3>
+
+<p>Allows you to set varous things if the rule is matched.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible Value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td rowspan="11">type <br/><small>(optional)</small></td>
+ <td>request (default)</td>
+ <td>The same as <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletRequest.html#setAttribute(java.lang.String,%20java.lang.Object)">setAttribute</a>([name],
+ [value])</code>
+ (note, name must be set).</td>
+ </tr>
+ <tr>
+ <td>session</td>
+ <td>The same as <code>request.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletRequest.html#getSession()">getSesison</a>(true).<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpSession.html#setAttribute(java.lang.String,%20java.lang.Object)">setAttribute</a>([name],
+ [value])</code>
+ (note, name must be set).</td>
+ </tr>
+ <tr>
+ <td>response-header</td>
+ <td>The same as <code>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletResponse.html#setHeader(java.lang.String,%20java.lang.String)">setHeader</a>([name],
+ [value])</code>
+ (note, name must be set).</td>
+ </tr>
+ <tr>
+ <td>cookie</td>
+ <td>
+ Value can be in the format "[value][:domain[:lifetime[:path]]]".
+ This sets a cookie on the client's browser. The cookie's name is specified by the name attribute. The domain
+ field is the domain of the cookie, such as '.apache.org',the optional lifetime is the lifetime of the cookie
+ in seconds, and the optional path is the path of the cookie (note, name must be set).
+ </td>
+ </tr>
+ <tr>
+ <td>status</td>
+ <td>The same as <code>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/http/HttpServletResponse.html#setStatus(int)">setStatus</a>([value])
+ </code></td>
+ </tr>
+ <tr>
+ <td>content-type</td>
+ <td>The same as <code>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletResponse.html#setContentType(java.lang.String)">setContentType</a>([value])
+ </code></td>
+ </tr>
+ <tr>
+ <td>charset</td>
+ <td>The same as <code>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletResponse.html#setCharacterEncoding(java.lang.String)">setCharacterEncoding</a>([value])
+ </code></td>
+ </tr>
+ <tr>
+ <td>expires</td>
+ <td>Will set the Expires HTTP header by adding the time specified and current time
+ (this is <a href="http://httpd.apache.org/docs/2.0/mod/mod_expires.html">mod_expires</a> style). Syntax "{num type}*".
+ Units can be (singular or plural);
+ years, months, weeks, days, hours, minutes, seconds.
+ <br/>eg, "1 day 2 seconds", "3 hours", "1 year 1 hour"
+ </td>
+ </tr>
+ <tr>
+ <td>locale</td>
+ <td>The same as <code>response.<a
+ href="http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletResponse.html#setLocale(java.util.Locale)">setLocale</a>([value])
+ </code>
+ specify the <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Locale.html">Locale</a> in the format
+ (valid
+ locales are, zh, zh-CN, zh-CN-southern i.e. "-" separating the language, country and variant (if any)).
+ </td>
+ </tr>
+ <tr>
+ <td>parameter</td>
+ <td>Enables you to override a <code>request.getParameter(String)</code> wuth a custom value</td>
+ </tr>
+ <tr>
+ <td>method</td>
+ <td>Enables you to override <code>request.getMethod()</code> with a custom value</td>
+ </tr>
+ <tr>
+ <td>name <br/><small>(optional)</small></td>
+ <td>(can be anything)</td>
+ <td>If type is request, session, response-header, cookie this specifies the name item.</td>
+ </tr>
+</table>
+
+<p>In the following example a request attribute "client" will be set to "AvantGo" or "Samsung SCH-6100", this can be
+ fetched in a servlet or
+ JSP using <code>request.getAttribute("client")</code>.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;condition name="user-agent"&gt;Mozilla/3\.0 (compatible; AvantGo .*)&lt;/from&gt;
+ &lt;from&gt;.*&lt;/from&gt;
+ <b>&lt;set name="client"&gt;AvantGo&lt;/set&gt;</b>
+ &lt;/rule&gt;
+ &lt;rule&gt;
+ &lt;condition name="user-agent"&gt;UP\.Browser/3.*SC03 .* &lt;/from&gt;
+ &lt;from&gt;.*&lt;/from&gt;
+ <b>&lt;set name="client"&gt;Samsung SCH-6100&lt;/set&gt;</b>
+ &lt;/rule&gt;
+</code></pre>
+
+<p>It is also possible to use regular replacement expressions as part of the
+ value similar to their usage in &lt;to&gt; elements:</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;/products/(.*)/(.*)/index.html&lt;/from&gt;
+ <b>&lt;set name=&quot;urlrewrite.product.slug&quot;&gt;$1&lt;/set&gt;</b>
+ <b>&lt;set name=&quot;urlrewrite.product.id&quot;&gt;$2&lt;/set&gt;</b>
+ &lt;to&gt;/products?slug=$1&amp;id=$2&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<a name="run"> </a>
+<h3>&lt;run&gt; element</h3>
+
+<p>Allows you to run a method on an object when a rule and it's conditions are matched.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Possible value</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td>class</td>
+ <td> </td>
+ <td>The class you want to run a method on. Must be a fully qualified name.</td>
+ </tr>
+ <tr>
+ <td>method (optional)</td>
+ <td>run (default)</td>
+ <td>The method you want to run, the method must have the parameters (HttpServletRequest, HttpServletResponse)
+ e.g. <code>run(HttpServletRequest request, HttpServletResponse response)</code>
+ <br/>Note, if <code>init(ServletConfig)</code> or <code>destroy()</code> is found they will be run at when
+ creating
+ or destroying an instance.
+ </td>
+ </tr>
+ <tr>
+ <td rowspan="2">neweachtime (optional)</td>
+ <td>false (default)</td>
+ <td>One instance for each UrlRewriteFilter instance.</td>
+ </tr>
+ <tr>
+ <td>true</td>
+ <td>A new instance of the class will be created before running each time set to true.</td>
+ </tr>
+</table>
+
+<p>When the rule in the following example is matched, <code>WorldServlet.goGet(HttpServletRequest,
+ HttpServletResponse)</code>
+ will be invoked, the request will then be forwarded to <code>/world-presentation.jsp</code>.</p>
+
+<pre><code>
+ &lt;rule&gt;
+ &lt;from&gt;^/world/[a-z]+/[a-z]+$&lt;/from&gt;
+ <b>&lt;run class="com.blah.web.WorldServlet" method="doGet" /&gt;</b>
+ &lt;to&gt;/world-presentation.jsp&lt;/to&gt;
+ &lt;/rule&gt;
+</code></pre>
+
+<p>Note, you can specify init-param's the same way you would for a servlet.</p>
+
+<pre><code>
+ &lt;run class="com.blah.web.MyServlet" method="doGet"&gt;
+ &lt;init-param&gt;
+ &lt;param-name&gt;someParamName&lt;/param-name&gt;
+ &lt;param-value&gt;10&lt;/param-value&gt;
+ &lt;/init-param&gt;
+ &lt;/run&gt;
+</code></pre>
+
+<p>If the method being called throws an Exception the original exception will be re-thrown as if it were the original
+ if it extends RuntimeException (eg, NullPointer), other exceptions are wrapped in a ServletException and thrown
+ so your container can handle them.</p>
+
+
+<a name="class-rule"> </a>
+<h3>&lt;class-rule&gt; element</h3>
+
+<p>Allows you to run a method every time a request come in for 100% dynamic rules. See the org.tuckey.web.filters.urlrewrite.sample package for an example.</p>
+
+<table cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td>class</td>
+ <td>The class you want to run a method on. Must be a fully qualified name.</td>
+ </tr>
+ <tr>
+ <td>method (optional, default matches)</td>
+ <td>The method you want to run, the method must have the parameters (HttpServletRequest, HttpServletResponse)
+ e.g. <code>run(HttpServletRequest request, HttpServletResponse response)</code>
+ <br/>Note, if <code>init(ServletConfig)</code> or <code>destroy()</code> is found they will be run at when
+ creating or destroying an instance.
+ </td>
+ </tr>
+ <tr>
+ <td>last (optional, default true</td>
+ <td>If false more rules will be processed following this rule even if it is matched (so that a better match may be found).</td>
+ </tr>
+</table>
+
+<p>Example:</p>
+
+<pre><code>
+ &lt;class-rule class="com.blah.web.MyRuleClass" /&gt;
+</code></pre>
+
+
+<a name="tips"> </a>