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