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 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 }