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 }