View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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 MsieSslRule} - disables the keep alive on SSL for IE5 and IE6. </li>
54   * <li> {@link LegacyRule} - the old version of rewrite. </li>
55   * <li> {@link ForwardedSchemeHeaderRule} - set the scheme according to the headers present. </li>
56   * <li> {@link VirtualHostRuleContainer} - checks whether the request matches one of a set of virtual host names.</li>
57   * </ul>
58   *
59   *
60   * Here is a typical jetty.xml configuration would be: <pre>
61   *
62   *     &lt;New id="RewriteHandler" 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  *     &lt;/New&gt;
147  * 
148  *     &lt;Set name="handler"&gt;
149  *       &lt;New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"&gt;
150  *         &lt;Set name="handlers"&gt;
151  *           &lt;Array type="org.eclipse.jetty.server.Handler"&gt;
152  *             &lt;Item&gt;
153  *               &lt;Ref id="RewriteHandler"/&gt;
154  *             &lt;/Item&gt;
155  *             &lt;Item&gt;
156  *               &lt;New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/&gt;
157  *             &lt;/Item&gt;
158  *             &lt;Item&gt;
159  *               &lt;New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/&gt;
160  *             &lt;/Item&gt;
161  *             &lt;Item&gt;
162  *               &lt;New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/&gt;
163  *             &lt;/Item&gt;
164  *           &lt;/Array&gt;
165  *         &lt;/Set&gt;
166  *       &lt;/New&gt;
167  *     &lt;/Set&gt;
168  * </pre>
169  *
170  */
171 public class RewriteHandler extends HandlerWrapper
172 {
173 
174     private RuleContainer _rules;
175 
176     /* ------------------------------------------------------------ */
177     public RewriteHandler()
178     {
179         _rules = new RuleContainer();
180     }
181 
182     /* ------------------------------------------------------------ */
183     /**
184      * To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and
185      * originalPathAttribute
186      *
187      * @param legacyRule old style rewrite rule
188      */
189     @Deprecated
190     public void setLegacyRule(LegacyRule legacyRule)
191     {
192         _rules.setLegacyRule(legacyRule);
193     }
194 
195     /* ------------------------------------------------------------ */
196     /**
197      * Returns the list of rules.
198      * @return an array of {@link Rule}.
199      */
200     public Rule[] getRules()
201     {
202         return _rules.getRules();
203     }
204 
205     /* ------------------------------------------------------------ */
206     /**
207      * Assigns the rules to process.
208      * @param rules an array of {@link Rule}.
209      */
210     public void setRules(Rule[] rules)
211     {
212         _rules.setRules(rules);
213     }
214 
215     /*------------------------------------------------------------ */
216     /**
217      * Assigns the rules to process.
218      * @param rules a {@link RuleContainer} containing other rules to process
219      */
220     public void setRules(RuleContainer rules)
221     {
222         _rules = rules;
223     }
224 
225     /* ------------------------------------------------------------ */
226     /**
227      * Add a Rule
228      * @param rule The rule to add to the end of the rules array
229      */
230     public void addRule(Rule rule)
231     {
232         _rules.addRule(rule);
233     }
234 
235     /* ------------------------------------------------------------ */
236     /**
237      * @return the rewriteRequestURI If true, this handler will rewrite the value
238      * returned by {@link HttpServletRequest#getRequestURI()}.
239      */
240     public boolean isRewriteRequestURI()
241     {
242         return _rules.isRewriteRequestURI();
243     }
244 
245     /* ------------------------------------------------------------ */
246     /**
247      * @param rewriteRequestURI true if this handler will rewrite the value
248      * returned by {@link HttpServletRequest#getRequestURI()}.
249      */
250     public void setRewriteRequestURI(boolean rewriteRequestURI)
251     {
252         _rules.setRewriteRequestURI(rewriteRequestURI);
253     }
254 
255     /* ------------------------------------------------------------ */
256     /**
257      * @return true if this handler will rewrite the value
258      * returned by {@link HttpServletRequest#getPathInfo()}.
259      */
260     public boolean isRewritePathInfo()
261     {
262         return _rules.isRewritePathInfo();
263     }
264 
265     /* ------------------------------------------------------------ */
266     /**
267      * @param rewritePathInfo true if this handler will rewrite the value
268      * returned by {@link HttpServletRequest#getPathInfo()}.
269      */
270     public void setRewritePathInfo(boolean rewritePathInfo)
271     {
272         _rules.setRewritePathInfo(rewritePathInfo);
273     }
274 
275     /* ------------------------------------------------------------ */
276     /**
277      * @return the originalPathAttribte. If non null, this string will be used
278      * as the attribute name to store the original request path.
279      */
280     public String getOriginalPathAttribute()
281     {
282         return _rules.getOriginalPathAttribute();
283     }
284 
285     /* ------------------------------------------------------------ */
286     /**
287      * @param originalPathAttribute If non null, this string will be used
288      * as the attribute name to store the original request path.
289      */
290     public void setOriginalPathAttribute(String originalPathAttribute)
291     {
292         _rules.setOriginalPathAttribute(originalPathAttribute);
293     }
294 
295 
296     /* ------------------------------------------------------------ */
297     /* (non-Javadoc)
298      * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
299      */
300     @Override
301     public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
302     {
303         if (isStarted())
304         {
305             String returned = _rules.matchAndApply(target, request, response);
306             target = (returned == null) ? target : returned;
307 
308             if (!baseRequest.isHandled())
309                 super.handle(target, baseRequest, request, response);
310         }
311     }
312 
313 }