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