View Javadoc

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