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 * <Set name="handler">
59 * <New id="Handlers" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
60 * <Set name="rules">
61 * <Array type="org.eclipse.jetty.rewrite.handler.Rule">
62 *
63 * <Item>
64 * <New id="rewrite" class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
65 * <Set name="pattern">/*</Set>
66 * <Set name="replacement">/test</Set>
67 * </New>
68 * </Item>
69 *
70 * <Item>
71 * <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule">
72 * <Set name="pattern">/session/</Set>
73 * <Set name="code">400</Set>
74 * <Set name="reason">Setting error code 400</Set>
75 * </New>
76 * </Item>
77 *
78 * <Item>
79 * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
80 * <Set name="pattern">*.jsp</Set>
81 * <Set name="name">server</Set>
82 * <Set name="value">dexter webserver</Set>
83 * </New>
84 * </Item>
85 *
86 * <Item>
87 * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
88 * <Set name="pattern">*.jsp</Set>
89 * <Set name="name">title</Set>
90 * <Set name="value">driven header purpose</Set>
91 * </New>
92 * </Item>
93 *
94 * <Item>
95 * <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule">
96 * <Set name="pattern">/test/dispatch</Set>
97 * <Set name="location">http://jetty.eclipse.org</Set>
98 * </New>
99 * </Item>
100 *
101 * <Item>
102 * <New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule">
103 * <Set name="regex">/test-jaas/$</Set>
104 * <Set name="replacement">/demo</Set>
105 * </New>
106 * </Item>
107 *
108 * <Item>
109 * <New id="forwardedHttps" class="org.eclipse.jetty.rewrite.handler.ForwardedSchemeHeaderRule">
110 * <Set name="header">X-Forwarded-Scheme</Set>
111 * <Set name="headerValue">https</Set>
112 * <Set name="scheme">https</Set>
113 * </New>
114 * </Item>
115 *
116 * <Item>
117 * <New id="virtualHost" class="org.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer">
118 *
119 * <Set name="virtualHosts">
120 * <Array type="java.lang.String">
121 * <Item>eclipse.com</Item>
122 * <Item>www.eclipse.com</Item>
123 * <Item>eclipse.org</Item>
124 * <Item>www.eclipse.org</Item>
125 * </Array>
126 * </Set>
127 *
128 * <Call name="addRule">
129 * <Arg>
130 * <New class="org.eclipse.jetty.rewrite.handler.CookiePatternRule">
131 * <Set name="pattern">/*</Set>
132 * <Set name="name">CookiePatternRule</Set>
133 * <Set name="value">1</Set>
134 * </New>
135 * </Arg>
136 * </Call>
137 *
138 * </New>
139 * </ Item>
140 *
141 * </Array>
142 * </Set>
143 *
144 * <Set name="handler">
145 * <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
146 * <Set name="handlers">
147 * <Array type="org.eclipse.jetty.server.Handler">
148 * <Item>
149 * <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
150 * </Item>
151 * <Item>
152 * <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
153 * </Item>
154 * <Item>
155 * <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/>
156 * </Item>
157 * </Array>
158 * </Set>
159 * </New>
160 * </Set>
161 *
162 * </New>
163 * </Set>
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 }