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