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