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.server.Request;
23 import org.eclipse.jetty.server.handler.HandlerWrapper;
24
25 /* ------------------------------------------------------------ */
26 /**
27 *<p> Rewrite handler is responsible for managing the rules. Its capabilities
28 * is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule.
29 * There is also handling for cookies, headers, redirection, setting status or error codes
30 * whenever the rule finds a match.
31 *
32 * <p> The rules can be matched by the either: pattern matching of PathMap
33 * (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set
34 * (eg {@link MsieSslRule} - the requests must be in SSL mode).
35 *
36 * <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only
37 * be applied if the request matches the conditions for their container
38 * (e.g., by virtual host name)
39 *
40 * <p>The list of predefined rules is:
41 * <ul>
42 * <li> {@link CookiePatternRule} - adds a new cookie in response. </li>
43 * <li> {@link HeaderPatternRule} - adds/modifies the HTTP headers in response. </li>
44 * <li> {@link RedirectPatternRule} - sets the redirect location. </li>
45 * <li> {@link ResponsePatternRule} - sets the status/error codes. </li>
46 * <li> {@link RewritePatternRule} - rewrites the requested URI. </li>
47 * <li> {@link RewriteRegexRule} - rewrites the requested URI using regular expression for pattern matching. </li>
48 * <li> {@link ProxyRule} - proxies the requested URI to the host defined in proxyTo. </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="rewrite" class="org.eclipse.jetty.rewrite.handler.ProxyRule">
72 * <Set name="pattern">/*</Set>
73 * <Set name="proxyTo">http://webtide.com:8080</Set>
74 * </New>
75 * </Item>
76 *
77 * <Item>
78 * <New id="response" class="org.eclipse.jetty.rewrite.handler.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.eclipse.jetty.rewrite.handler.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.eclipse.jetty.rewrite.handler.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.eclipse.jetty.rewrite.handler.RedirectPatternRule">
103 * <Set name="pattern">/test/dispatch</Set>
104 * <Set name="location">http://jetty.eclipse.org</Set>
105 * </New>
106 * </Item>
107 *
108 * <Item>
109 * <New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.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.eclipse.jetty.rewrite.handler.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.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer">
125 *
126 * <Set name="virtualHosts">
127 * <Array type="java.lang.String">
128 * <Item>eclipse.com</Item>
129 * <Item>www.eclipse.com</Item>
130 * <Item>eclipse.org</Item>
131 * <Item>www.eclipse.org</Item>
132 * </Array>
133 * </Set>
134 *
135 * <Call name="addRule">
136 * <Arg>
137 * <New class="org.eclipse.jetty.rewrite.handler.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.eclipse.jetty.server.handler.HandlerCollection">
153 * <Set name="handlers">
154 * <Array type="org.eclipse.jetty.server.Handler">
155 * <Item>
156 * <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
157 * </Item>
158 * <Item>
159 * <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
160 * </Item>
161 * <Item>
162 * <New id="RequestLog" class="org.eclipse.jetty.server.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 @Deprecated
193 public void setLegacyRule(LegacyRule legacyRule)
194 {
195 _rules.setLegacyRule(legacyRule);
196 }
197
198 /* ------------------------------------------------------------ */
199 /**
200 * Returns the list of rules.
201 * @return an array of {@link Rule}.
202 */
203 public Rule[] getRules()
204 {
205 return _rules.getRules();
206 }
207
208 /* ------------------------------------------------------------ */
209 /**
210 * Assigns the rules to process.
211 * @param rules an array of {@link Rule}.
212 */
213 public void setRules(Rule[] rules)
214 {
215 _rules.setRules(rules);
216 }
217
218 /*------------------------------------------------------------ */
219 /**
220 * Assigns the rules to process.
221 * @param rules a {@link RuleContainer} containing other rules to process
222 */
223 public void setRules(RuleContainer rules)
224 {
225 _rules = rules;
226 }
227
228 /* ------------------------------------------------------------ */
229 /**
230 * Add a Rule
231 * @param rule The rule to add to the end of the rules array
232 */
233 public void addRule(Rule rule)
234 {
235 _rules.addRule(rule);
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 originalPathAttribute 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 /* (non-Javadoc)
301 * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
302 */
303 @Override
304 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
305 {
306 if (isStarted())
307 {
308 String returned = _rules.matchAndApply(target, request, response);
309 target = (returned == null) ? target : returned;
310
311 if (!baseRequest.isHandled())
312 super.handle(target, baseRequest, request, response);
313 }
314 }
315
316 }