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 }