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