View Javadoc

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