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.http.PathMap; 23 import org.eclipse.jetty.server.Request; 24 import org.eclipse.jetty.server.handler.HandlerWrapper; 25 26 /* ------------------------------------------------------------ */ 27 /** 28 *<p> Rewrite handler is responsible for managing the rules. Its capabilities 29 * is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule. 30 * There is also handling for cookies, headers, redirection, setting status or error codes 31 * whenever the rule finds a match. 32 * 33 * <p> The rules can be matched by the either: pattern matching of PathMap 34 * (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set 35 * (eg {@link MsieSslRule} - the requests must be in SSL mode). 36 * 37 * <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only 38 * be applied if the request matches the conditions for their container 39 * (e.g., by virtual host name) 40 * 41 * <p>The list of predefined rules is: 42 * <ul> 43 * <li> {@link CookiePatternRule} - adds a new cookie in response. </li> 44 * <li> {@link HeaderPatternRule} - adds/modifies the HTTP headers in response. </li> 45 * <li> {@link RedirectPatternRule} - sets the redirect location. </li> 46 * <li> {@link ResponsePatternRule} - sets the status/error codes. </li> 47 * <li> {@link RewritePatternRule} - rewrites the requested URI. </li> 48 * <li> {@link RewriteRegexRule} - rewrites the requested URI using regular expression for pattern matching. </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 * <Set name="handler"> 59 * <New id="Handlers" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"> 60 * <Set name="rules"> 61 * <Array type="org.eclipse.jetty.rewrite.handler.Rule"> 62 * 63 * <Item> 64 * <New id="rewrite" class="org.eclipse.jetty.rewrite.handler.RewritePatternRule"> 65 * <Set name="pattern">/*</Set> 66 * <Set name="replacement">/test</Set> 67 * </New> 68 * </Item> 69 * 70 * <Item> 71 * <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule"> 72 * <Set name="pattern">/session/</Set> 73 * <Set name="code">400</Set> 74 * <Set name="reason">Setting error code 400</Set> 75 * </New> 76 * </Item> 77 * 78 * <Item> 79 * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> 80 * <Set name="pattern">*.jsp</Set> 81 * <Set name="name">server</Set> 82 * <Set name="value">dexter webserver</Set> 83 * </New> 84 * </Item> 85 * 86 * <Item> 87 * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> 88 * <Set name="pattern">*.jsp</Set> 89 * <Set name="name">title</Set> 90 * <Set name="value">driven header purpose</Set> 91 * </New> 92 * </Item> 93 * 94 * <Item> 95 * <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule"> 96 * <Set name="pattern">/test/dispatch</Set> 97 * <Set name="location">http://jetty.eclipse.org</Set> 98 * </New> 99 * </Item> 100 * 101 * <Item> 102 * <New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule"> 103 * <Set name="regex">/test-jaas/$</Set> 104 * <Set name="replacement">/demo</Set> 105 * </New> 106 * </Item> 107 * 108 * <Item> 109 * <New id="forwardedHttps" class="org.eclipse.jetty.rewrite.handler.ForwardedSchemeHeaderRule"> 110 * <Set name="header">X-Forwarded-Scheme</Set> 111 * <Set name="headerValue">https</Set> 112 * <Set name="scheme">https</Set> 113 * </New> 114 * </Item> 115 * 116 * <Item> 117 * <New id="virtualHost" class="org.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer"> 118 * 119 * <Set name="virtualHosts"> 120 * <Array type="java.lang.String"> 121 * <Item>eclipse.com</Item> 122 * <Item>www.eclipse.com</Item> 123 * <Item>eclipse.org</Item> 124 * <Item>www.eclipse.org</Item> 125 * </Array> 126 * </Set> 127 * 128 * <Call name="addRule"> 129 * <Arg> 130 * <New class="org.eclipse.jetty.rewrite.handler.CookiePatternRule"> 131 * <Set name="pattern">/*</Set> 132 * <Set name="name">CookiePatternRule</Set> 133 * <Set name="value">1</Set> 134 * </New> 135 * </Arg> 136 * </Call> 137 * 138 * </New> 139 * </ Item> 140 * 141 * </Array> 142 * </Set> 143 * 144 * <Set name="handler"> 145 * <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> 146 * <Set name="handlers"> 147 * <Array type="org.eclipse.jetty.server.Handler"> 148 * <Item> 149 * <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/> 150 * </Item> 151 * <Item> 152 * <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/> 153 * </Item> 154 * <Item> 155 * <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/> 156 * </Item> 157 * </Array> 158 * </Set> 159 * </New> 160 * </Set> 161 * 162 * </New> 163 * </Set> 164 * </pre> 165 * 166 */ 167 public class RewriteHandler extends HandlerWrapper 168 { 169 170 private RuleContainer _rules; 171 172 /* ------------------------------------------------------------ */ 173 public RewriteHandler() 174 { 175 _rules = new RuleContainer(); 176 } 177 178 /* ------------------------------------------------------------ */ 179 /** 180 * To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and 181 * originalPathAttribute 182 * 183 * @param legacyRule old style rewrite rule 184 */ 185 @Deprecated 186 public void setLegacyRule(LegacyRule legacyRule) 187 { 188 _rules.setLegacyRule(legacyRule); 189 } 190 191 /* ------------------------------------------------------------ */ 192 /** 193 * Returns the list of rules. 194 * @return an array of {@link Rule}. 195 */ 196 public Rule[] getRules() 197 { 198 return _rules.getRules(); 199 } 200 201 /* ------------------------------------------------------------ */ 202 /** 203 * Assigns the rules to process. 204 * @param rules an array of {@link Rule}. 205 */ 206 public void setRules(Rule[] rules) 207 { 208 _rules.setRules(rules); 209 } 210 211 /*------------------------------------------------------------ */ 212 /** 213 * Assigns the rules to process. 214 * @param rules a {@link RuleContainer} containing other rules to process 215 */ 216 public void setRules(RuleContainer rules) 217 { 218 _rules = rules; 219 } 220 221 /* ------------------------------------------------------------ */ 222 /** 223 * Add a Rule 224 * @param rule The rule to add to the end of the rules array 225 */ 226 public void addRule(Rule rule) 227 { 228 _rules.addRule(rule); 229 } 230 231 /* ------------------------------------------------------------ */ 232 /** 233 * @return the rewriteRequestURI If true, this handler will rewrite the value 234 * returned by {@link HttpServletRequest#getRequestURI()}. 235 */ 236 public boolean isRewriteRequestURI() 237 { 238 return _rules.isRewriteRequestURI(); 239 } 240 241 /* ------------------------------------------------------------ */ 242 /** 243 * @param rewriteRequestURI true if this handler will rewrite the value 244 * returned by {@link HttpServletRequest#getRequestURI()}. 245 */ 246 public void setRewriteRequestURI(boolean rewriteRequestURI) 247 { 248 _rules.setRewriteRequestURI(rewriteRequestURI); 249 } 250 251 /* ------------------------------------------------------------ */ 252 /** 253 * @return true if this handler will rewrite the value 254 * returned by {@link HttpServletRequest#getPathInfo()}. 255 */ 256 public boolean isRewritePathInfo() 257 { 258 return _rules.isRewritePathInfo(); 259 } 260 261 /* ------------------------------------------------------------ */ 262 /** 263 * @param rewritePathInfo true if this handler will rewrite the value 264 * returned by {@link HttpServletRequest#getPathInfo()}. 265 */ 266 public void setRewritePathInfo(boolean rewritePathInfo) 267 { 268 _rules.setRewritePathInfo(rewritePathInfo); 269 } 270 271 /* ------------------------------------------------------------ */ 272 /** 273 * @return the originalPathAttribte. If non null, this string will be used 274 * as the attribute name to store the original request path. 275 */ 276 public String getOriginalPathAttribute() 277 { 278 return _rules.getOriginalPathAttribute(); 279 } 280 281 /* ------------------------------------------------------------ */ 282 /** 283 * @param originalPathAttribute If non null, this string will be used 284 * as the attribute name to store the original request path. 285 */ 286 public void setOriginalPathAttribute(String originalPathAttribute) 287 { 288 _rules.setOriginalPathAttribute(originalPathAttribute); 289 } 290 291 292 /* ------------------------------------------------------------ */ 293 /* (non-Javadoc) 294 * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) 295 */ 296 @Override 297 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 298 { 299 if (isStarted()) 300 { 301 String returned = _rules.matchAndApply(target, request, response); 302 target = (returned == null) ? target : returned; 303 304 if (!baseRequest.isHandled()) 305 super.handle(target, baseRequest, request, response); 306 } 307 } 308 309 }