View Javadoc

    1   //========================================================================
    2   //$Id: RewriteHandler.java 1143 2008-07-23 05:03:31Z gregw $
    3   //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
    4   //------------------------------------------------------------------------
    5   //Licensed under the Apache License, Version 2.0 (the "License");
    6   //you may not use this file except in compliance with the License.
    7   //You may obtain a copy of the License at
    8   //http://www.apache.org/licenses/LICENSE-2.0
    9   //Unless required by applicable law or agreed to in writing, software
    10  //distributed under the License is distributed on an "AS IS" BASIS,
    11  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //See the License for the specific language governing permissions and
    13  //limitations under the License.
    14  //========================================================================
    15  package org.mortbay.jetty.handler.rewrite;
    16
    17  import java.io.IOException;
    18
    19  import javax.servlet.ServletException;
    20  import javax.servlet.http.HttpServletRequest;
    21  import javax.servlet.http.HttpServletResponse;
    22
    23  import org.mortbay.jetty.HttpConnection;
    24  import org.mortbay.jetty.Request;
    25  import org.mortbay.jetty.handler.HandlerWrapper;
    26  import org.mortbay.jetty.servlet.PathMap;
    27  import org.mortbay.log.Log;
    28  import org.mortbay.util.LazyList;
    29
    30  /* ------------------------------------------------------------ */
    31  /**
    32   *<p> Rewrite handler is responsible for managing the rules. Its capabilities
    33   * is not only limited for url rewrites such as RewritePatternRule or RewriteRegexRule.
    34   * There is also handling for cookies, headers, redirection, setting status or error codes
    35   * whenever the rule finds a match.
    36   *
    37   * <p> The rules can be matched by the ff. options: pattern matching of PathMap
    38   * (class PatternRule), regular expressions (class RegexRule) or certain conditions set
    39   * (e.g. MsieSslRule - the requests must be in SSL mode).
    40   *
    41   * Here are the list of rules:
    42   * <ul>
    43   * <li> CookiePatternRule - adds a new cookie in response. </li>
    44   * <li> HeaderPatternRule - adds/modifies the HTTP headers in response. </li>
    45   * <li> RedirectPatternRule - sets the redirect location. </li>
    46   * <li> ResponsePatternRule - sets the status/error codes. </li>
    47   * <li> RewritePatternRule - rewrites the requested URI. </li>
    48   * <li> RewriteRegexRule - rewrites the requested URI using regular expression for pattern matching. </li>
    49   * <li> MsieSslRule - disables the keep alive on SSL for IE5 and IE6. </li>
    50   * <li> LegacyRule - the old version of rewrite. </li>
    51   * <li> ForwardedSchemeHeaderRule - set the scheme according to the headers present. </li>
    52   * </ul>
    53   *
    54   * <p> The rules can be grouped into rule containers (class RuleContainerRule), and will only
    55   * be applied if the request matches the conditions for their container
    56   * (e.g., by virtual host name)
    57   *
    58   * Here are a list of rule containers:
    59   * <ul>
    60   * <li> VirtualHostRuleContainerRule - checks whether the request matches one of a set of virtual host names.</li>
    61   * </ul>
    62   *
    63   * Here is a typical jetty.xml configuration would be: <pre>
    64   *
    65   *   &lt;Set name="handler"&gt;
    66   *     &lt;New id="Handlers" class="org.mortbay.jetty.handler.rewrite.RewriteHandler"&gt;
    67   *       &lt;Set name="rules"&gt;
    68   *         &lt;Array type="org.mortbay.jetty.handler.rewrite.Rule"&gt;
    69   *
    70   *           &lt;Item&gt;
    71   *             &lt;New id="rewrite" class="org.mortbay.jetty.handler.rewrite.RewritePatternRule"&gt;
    72   *               &lt;Set name="pattern"&gt;/*&lt;/Set&gt;
    73   *               &lt;Set name="replacement"&gt;/test&lt;/Set&gt;
    74   *             &lt;/New&gt;
    75   *           &lt;/Item&gt;
    76   *
    77   *           &lt;Item&gt;
    78   *             &lt;New id="response" class="org.mortbay.jetty.handler.rewrite.ResponsePatternRule"&gt;
    79   *               &lt;Set name="pattern"&gt;/session/&lt;/Set&gt;
    80   *               &lt;Set name="code"&gt;400&lt;/Set&gt;
    81   *               &lt;Set name="reason"&gt;Setting error code 400&lt;/Set&gt;
    82   *             &lt;/New&gt;
    83   *           &lt;/Item&gt;
    84   *
    85   *           &lt;Item&gt;
    86   *             &lt;New id="header" class="org.mortbay.jetty.handler.rewrite.HeaderPatternRule"&gt;
    87   *               &lt;Set name="pattern"&gt;*.jsp&lt;/Set&gt;
    88   *               &lt;Set name="name"&gt;server&lt;/Set&gt;
    89   *               &lt;Set name="value"&gt;dexter webserver&lt;/Set&gt;
    90   *             &lt;/New&gt;
    91   *           &lt;/Item&gt;
    92   *
    93   *           &lt;Item&gt;
    94   *             &lt;New id="header" class="org.mortbay.jetty.handler.rewrite.HeaderPatternRule"&gt;
    95   *               &lt;Set name="pattern"&gt;*.jsp&lt;/Set&gt;
    96   *               &lt;Set name="name"&gt;title&lt;/Set&gt;
    97   *               &lt;Set name="value"&gt;driven header purpose&lt;/Set&gt;
    98   *             &lt;/New&gt;
    99   *           &lt;/Item&gt;
    100  *
    101  *           &lt;Item&gt;
    102  *             &lt;New id="redirect" class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule"&gt;
    103  *               &lt;Set name="pattern"&gt;/test/dispatch&lt;/Set&gt;
    104  *               &lt;Set name="location"&gt;http://jetty.mortbay.org&lt;/Set&gt;
    105  *             &lt;/New&gt;
    106  *           &lt;/Item&gt;
    107  *
    108  *           &lt;Item&gt;
    109  *             &lt;New id="regexRewrite" class="org.mortbay.jetty.handler.rewrite.RewriteRegexRule"&gt;
    110  *               &lt;Set name="regex"&gt;/test-jaas/$&lt;/Set&gt;
    111  *               &lt;Set name="replacement"&gt;/demo&lt;/Set&gt;
    112  *             &lt;/New&gt;
    113  *           &lt;/Item&gt;
    114  *
    115  *           &lt;Item&gt;
    116  *             &lt;New id="forwardedHttps" class="org.mortbay.jetty.handler.rewrite.ForwardedSchemeHeaderRule"&gt;
    117  *               &lt;Set name="header"&gt;X-Forwarded-Scheme&lt;/Set&gt;
    118  *               &lt;Set name="headerValue"&gt;https&lt;/Set&gt;
    119  *               &lt;Set name="scheme"&gt;https&lt;/Set&gt;
    120  *             &lt;/New&gt;
    121  *           &lt;/Item&gt;
    122  *
    123  *           &lt;Item&gt;
    124  *             &lt;New id="virtualHost" class="org.mortbay.jetty.handler.rewrite.VirtualHostRuleContainer"&gt;
    125  *
    126  *               &lt;Set name="virtualHosts"&gt;
    127  *                 &lt;Array type="java.lang.String"&gt;
    128  *                   &lt;Item&gt;mortbay.com&lt;/Item&gt;
    129  *                   &lt;Item&gt;www.mortbay.com&lt;/Item&gt;
    130  *                   &lt;Item&gt;mortbay.org&lt;/Item&gt;
    131  *                   &lt;Item&gt;www.mortbay.org&lt;/Item&gt;
    132  *                 &lt;/Array&gt;
    133  *               &lt;/Set&gt;
    134  *
    135  *               &lt;Call name="addRule"&gt;
    136  *                 &lt;Arg&gt;
    137  *                   &lt;New class="org.mortbay.jetty.handler.rewrite.CookiePatternRule"&gt;
    138  *                     &lt;Set name="pattern"&gt;/*&lt;/Set&gt;
    139  *                     &lt;Set name="name"&gt;CookiePatternRule&lt;/Set&gt;
    140  *                     &lt;Set name="value"&gt;1&lt;/Set&gt;
    141  *                   &lt;/New&gt;
    142  *                 &lt;/Arg&gt;
    143  *               &lt;/Call&gt;
    144  *
    145  *             &lt;/New&gt;
    146  *           &lt;/      Item&gt;
    147  *
    148  *         &lt;/Array&gt;
    149  *       &lt;/Set&gt;
    150  *
    151  *       &lt;Set name="handler"&gt;
    152  *         &lt;New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection"&gt;
    153  *           &lt;Set name="handlers"&gt;
    154  *            &lt;Array type="org.mortbay.jetty.Handler"&gt;
    155  *              &lt;Item&gt;
    156  *                &lt;New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/&gt;
    157  *              &lt;/Item&gt;
    158  *              &lt;Item&gt;
    159  *                &lt;New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/&gt;
    160  *              &lt;/Item&gt;
    161  *              &lt;Item&gt;
    162  *                &lt;New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/&gt;
    163  *              &lt;/Item&gt;
    164  *            &lt;/Array&gt;
    165  *           &lt;/Set&gt;
    166  *         &lt;/New&gt;
    167  *       &lt;/Set&gt;
    168  *
    169  *     &lt;/New&gt;
    170  *   &lt;/Set&gt;
    171  * </pre>
    172  *
    173  */
    174 public class RewriteHandler extends HandlerWrapper
    175 {
    176
    177     private RuleContainer _rules;
    178
    179     /* ------------------------------------------------------------ */
    180     public RewriteHandler()
    181     {
    182         _rules = new RuleContainer();
    183     }
    184
    185     /* ------------------------------------------------------------ */
    186     /**
    187      * To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and
    188      * originalPathAttribute
    189      *
    190      * @param legacyRule old style rewrite rule
    191      */
    192     public void setLegacyRule(LegacyRule legacyRule)
    193     {
    194         _rules.setLegacyRule(legacyRule);
    195     }
    196
    197     /* ------------------------------------------------------------ */
    198     /**
    199      * Returns the list of rules.
    200      * @return an array of {@link Rule}.
    201      */
    202     public Rule[] getRules()
    203     {
    204         return _rules.getRules();
    205     }
    206
    207     /* ------------------------------------------------------------ */
    208     /**
    209      * Assigns the rules to process.
    210      * @param rules an array of {@link Rule}.
    211      */
    212     public void setRules(Rule[] rules)
    213     {
    214         _rules.setRules(rules);
    215     }
    216
    217     /*------------------------------------------------------------ */
    218     /**
    219      * Assigns the rules to process.
    220      * @param rules a {@link RuleContainer} containing other rules to process
    221      */
    222     public void setRules(RuleContainer rules)
    223     {
    224         _rules = rules;
    225     }
    226
    227     /* ------------------------------------------------------------ */
    228     /**
    229      * Add a Rule
    230      * @param rule The rule to add to the end of the rules array
    231      */
    232     public void addRule(Rule rule)
    233     {
    234         _rules.addRule(rule);
    235     }
    236
    237
    238     /* ------------------------------------------------------------ */
    239     /**
    240      * @return the rewriteRequestURI If true, this handler will rewrite the value
    241      * returned by {@link HttpServletRequest#getRequestURI()}.
    242      */
    243     public boolean isRewriteRequestURI()
    244     {
    245         return _rules.isRewriteRequestURI();
    246     }
    247
    248     /* ------------------------------------------------------------ */
    249     /**
    250      * @param rewriteRequestURI true if this handler will rewrite the value
    251      * returned by {@link HttpServletRequest#getRequestURI()}.
    252      */
    253     public void setRewriteRequestURI(boolean rewriteRequestURI)
    254     {
    255         _rules.setRewriteRequestURI(rewriteRequestURI);
    256     }
    257
    258     /* ------------------------------------------------------------ */
    259     /**
    260      * @return true if this handler will rewrite the value
    261      * returned by {@link HttpServletRequest#getPathInfo()}.
    262      */
    263     public boolean isRewritePathInfo()
    264     {
    265         return _rules.isRewritePathInfo();
    266     }
    267
    268     /* ------------------------------------------------------------ */
    269     /**
    270      * @param rewritePathInfo true if this handler will rewrite the value
    271      * returned by {@link HttpServletRequest#getPathInfo()}.
    272      */
    273     public void setRewritePathInfo(boolean rewritePathInfo)
    274     {
    275         _rules.setRewritePathInfo(rewritePathInfo);
    276     }
    277
    278     /* ------------------------------------------------------------ */
    279     /**
    280      * @return the originalPathAttribte. If non null, this string will be used
    281      * as the attribute name to store the original request path.
    282      */
    283     public String getOriginalPathAttribute()
    284     {
    285         return _rules.getOriginalPathAttribute();
    286     }
    287
    288     /* ------------------------------------------------------------ */
    289     /**
    290      * @param originalPathAttribte If non null, this string will be used
    291      * as the attribute name to store the original request path.
    292      */
    293     public void setOriginalPathAttribute(String originalPathAttribute)
    294     {
    295         _rules.setOriginalPathAttribute(originalPathAttribute);
    296     }
    297
    298
    299     /* ------------------------------------------------------------ */
    300     /**
    301      * @deprecated
    302      */
    303     public PathMap getRewrite()
    304     {
    305         return _rules.getRewrite();
    306     }
    307
    308     /* ------------------------------------------------------------ */
    309     /**
    310      * @deprecated
    311      */
    312     public void setRewrite(PathMap rewrite)
    313     {
    314         _rules.setRewrite(rewrite);
    315     }
    316
    317     /* ------------------------------------------------------------ */
    318     /**
    319      * @deprecated
    320      */
    321     public void addRewriteRule(String pattern, String prefix)
    322     {
    323         _rules.addRewriteRule(pattern,prefix);
    324     }
    325
    326     /* ------------------------------------------------------------ */
    327     /* (non-Javadoc)
    328      * @see org.mortbay.jetty.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
    329      */
    330     public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
    331     {
    332         if (isStarted())
    333         {
    334             String returned = _rules.matchAndApply(target, request, response);
    335             target = (returned == null) ? target : returned;
    336
    337             if (!_rules.isHandled())
    338             {
    339                 super.handle(target, request, response, dispatch);
    340             }
    341         }
    342     }
    343
    344 }