1 //======================================================================== 2 //$Id$ 3 //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. 4 //------------------------------------------------------------------------ 5 //Licensed under the Apache License, Version 2.0 (the "License"); 6 //you may not use this file except in compliance with the License. 7 //You may obtain a copy of the License at 8 //http://www.apache.org/licenses/LICENSE-2.0 9 //Unless required by applicable law or agreed to in writing, software 10 //distributed under the License is distributed on an "AS IS" BASIS, 11 //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 //See the License for the specific language governing permissions and 13 //limitations under the License. 14 //======================================================================== 15 package org.mortbay.jetty.handler.rewrite; 16 17 import java.io.IOException; 18 19 import javax.servlet.ServletException; 20 import javax.servlet.http.HttpServletRequest; 21 import javax.servlet.http.HttpServletResponse; 22 23 import org.mortbay.jetty.HttpConnection; 24 import org.mortbay.jetty.Request; 25 import org.mortbay.jetty.handler.HandlerWrapper; 26 import org.mortbay.jetty.servlet.PathMap; 27 import org.mortbay.log.Log; 28 import org.mortbay.util.LazyList; 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 ff. options: pattern matching of PathMap 38 * (class PatternRule), regular expressions (class RegexRule) or certain conditions set 39 * (e.g. MsieSslRule - the requests must be in SSL mode). 40 * 41 * Here are the list of rules: 42 * <ul> 43 * <li> CookiePatternRule - adds a new cookie in response. </li> 44 * <li> HeaderPatternRule - adds/modifies the HTTP headers in response. </li> 45 * <li> RedirectPatternRule - sets the redirect location. </li> 46 * <li> ResponsePatternRule - sets the status/error codes. </li> 47 * <li> RewritePatternRule - rewrites the requested URI. </li> 48 * <li> RewriteRegexRule - rewrites the requested URI using regular expression for pattern matching. </li> 49 * <li> MsieSslRule - disables the keep alive on SSL for IE5 and IE6. </li> 50 * <li> LegacyRule - the old version of rewrite. </li> 51 * </ul> 52 * 53 * Here is a typical jetty.xml configuration would be: <pre> 54 * 55 * <Set name="handler"> 56 * <New id="Handlers" class="org.mortbay.jetty.handler.RewriteHandler"> 57 * <Set name="rules"> 58 * <Array type="org.mortbay.jetty.handler.rules.Rule"> 59 * 60 * <Item> 61 * <New id="rewrite" class="org.mortbay.jetty.handler.rules.RewritePatternRule"> 62 * <Set name="pattern">/*</Set> 63 * <Set name="replacement">/test</Set> 64 * </New> 65 * </Item> 66 * 67 * <Item> 68 * <New id="response" class="org.mortbay.jetty.handler.rules.ResponsePatternRule"> 69 * <Set name="pattern">/session/</Set> 70 * <Set name="code">400</Set> 71 * <Set name="reason">Setting error code 400</Set> 72 * </New> 73 * </Item> 74 * 75 * <Item> 76 * <New id="header" class="org.mortbay.jetty.handler.rules.HeaderPatternRule"> 77 * <Set name="pattern">*.jsp</Set> 78 * <Set name="name">server</Set> 79 * <Set name="value">dexter webserver</Set> 80 * </New> 81 * </Item> 82 * 83 * <Item> 84 * <New id="header" class="org.mortbay.jetty.handler.rules.HeaderPatternRule"> 85 * <Set name="pattern">*.jsp</Set> 86 * <Set name="name">title</Set> 87 * <Set name="value">driven header purpose</Set> 88 * </New> 89 * </Item> 90 * 91 * <Item> 92 * <New id="redirect" class="org.mortbay.jetty.handler.rules.RedirectPatternRule"> 93 * <Set name="pattern">/test/dispatch</Set> 94 * <Set name="location">http://jetty.mortbay.org</Set> 95 * </New> 96 * </Item> 97 * 98 * <Item> 99 * <New id="regexRewrite" class="org.mortbay.jetty.handler.rules.RewriteRegexRule"> 100 * <Set name="regex">/test-jaas/$</Set> 101 * <Set name="replacement">/demo</Set> 102 * </New> 103 * </Item> 104 * 105 * </Array> 106 * </Set> 107 * 108 * <Set name="handler"> 109 * <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection"> 110 * <Set name="handlers"> 111 * <Array type="org.mortbay.jetty.Handler"> 112 * <Item> 113 * <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/> 114 * </Item> 115 * <Item> 116 * <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/> 117 * </Item> 118 * <Item> 119 * <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/> 120 * </Item> 121 * </Array> 122 * </Set> 123 * </New> 124 * </Set> 125 * 126 * </New> 127 * </Set> 128 * </pre> 129 * 130 */ 131 public class RewriteHandler extends HandlerWrapper 132 { 133 private Rule[] _rules; 134 135 136 private String _originalPathAttribute; 137 private boolean _rewriteRequestURI=true; 138 private boolean _rewritePathInfo=true; 139 140 141 private LegacyRule _legacy; 142 143 /* ------------------------------------------------------------ */ 144 private LegacyRule getLegacyRule() 145 { 146 if (_legacy==null) 147 { 148 _legacy= new LegacyRule(); 149 addRule(_legacy); 150 } 151 return _legacy; 152 } 153 154 155 /* ------------------------------------------------------------ */ 156 /** 157 * To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and 158 * originalPathAttribute 159 * 160 * @param legacyRule old style rewrite rule 161 */ 162 public void setLegacyRule(LegacyRule legacyRule) 163 { 164 _legacy = legacyRule; 165 } 166 167 /* ------------------------------------------------------------ */ 168 /** 169 * Returns the list of rules. 170 * @return an array of {@link Rule}. 171 */ 172 public Rule[] getRules() 173 { 174 return _rules; 175 } 176 177 /* ------------------------------------------------------------ */ 178 /** 179 * Assigns the rules to process. 180 * @param rules an array of {@link Rule}. 181 */ 182 public void setRules(Rule[] rules) 183 { 184 if (_legacy==null) 185 _rules = rules; 186 else 187 { 188 _rules=null; 189 addRule(_legacy); 190 if (rules!=null) 191 for (Rule rule:rules) 192 addRule(rule); 193 } 194 } 195 196 /* ------------------------------------------------------------ */ 197 /** 198 * Add a Rule 199 * @param rule The rule to add to the end of the rules array 200 */ 201 public void addRule(Rule rule) 202 { 203 _rules = (Rule[])LazyList.addToArray(_rules,rule,Rule.class); 204 } 205 206 207 /* ------------------------------------------------------------ */ 208 /** 209 * @return the rewriteRequestURI If true, this handler will rewrite the value 210 * returned by {@link HttpServletRequest#getRequestURI()}. 211 */ 212 public boolean isRewriteRequestURI() 213 { 214 return _rewriteRequestURI; 215 } 216 217 /* ------------------------------------------------------------ */ 218 /** 219 * @param rewriteRequestURI true if this handler will rewrite the value 220 * returned by {@link HttpServletRequest#getRequestURI()}. 221 */ 222 public void setRewriteRequestURI(boolean rewriteRequestURI) 223 { 224 _rewriteRequestURI=rewriteRequestURI; 225 } 226 227 /* ------------------------------------------------------------ */ 228 /** 229 * @return true if this handler will rewrite the value 230 * returned by {@link HttpServletRequest#getPathInfo()}. 231 */ 232 public boolean isRewritePathInfo() 233 { 234 return _rewritePathInfo; 235 } 236 237 /* ------------------------------------------------------------ */ 238 /** 239 * @param rewritePathInfo true if this handler will rewrite the value 240 * returned by {@link HttpServletRequest#getPathInfo()}. 241 */ 242 public void setRewritePathInfo(boolean rewritePathInfo) 243 { 244 _rewritePathInfo=rewritePathInfo; 245 } 246 247 /* ------------------------------------------------------------ */ 248 /** 249 * @return the originalPathAttribte. If non null, this string will be used 250 * as the attribute name to store the original request path. 251 */ 252 public String getOriginalPathAttribute() 253 { 254 return _originalPathAttribute; 255 } 256 257 /* ------------------------------------------------------------ */ 258 /** 259 * @param originalPathAttribte If non null, this string will be used 260 * as the attribute name to store the original request path. 261 */ 262 public void setOriginalPathAttribute(String originalPathAttribte) 263 { 264 _originalPathAttribute=originalPathAttribte; 265 } 266 267 268 /* ------------------------------------------------------------ */ 269 /** 270 * @deprecated 271 */ 272 public PathMap getRewrite() 273 { 274 return getLegacyRule().getRewrite(); 275 } 276 277 /* ------------------------------------------------------------ */ 278 /** 279 * @deprecated 280 */ 281 public void setRewrite(PathMap rewrite) 282 { 283 getLegacyRule().setRewrite(rewrite); 284 } 285 286 /* ------------------------------------------------------------ */ 287 /** 288 * @deprecated 289 */ 290 public void addRewriteRule(String pattern, String prefix) 291 { 292 getLegacyRule().addRewriteRule(pattern,prefix); 293 } 294 295 /* ------------------------------------------------------------ */ 296 /* (non-Javadoc) 297 * @see org.mortbay.jetty.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) 298 */ 299 public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException 300 { 301 if (isStarted()) 302 { 303 boolean handled=false; 304 305 boolean original_set=_originalPathAttribute==null; 306 307 for (int i = 0, len= _rules.length; i < len; i++) 308 { 309 Rule rule = _rules[i]; 310 311 String applied=rule.matchAndApply(target,request, response); 312 if (applied!=null) 313 { 314 Log.debug("applied {}",rule); 315 if (!target.equals(applied)) 316 { 317 Log.debug("rewrote {} to {}",target,applied); 318 if (!original_set) 319 { 320 original_set=true; 321 request.setAttribute(_originalPathAttribute, target); 322 } 323 324 if (_rewriteRequestURI) 325 ((Request)request).setRequestURI(applied); 326 327 if (_rewritePathInfo) 328 ((Request)request).setPathInfo(applied); 329 330 target=applied; 331 } 332 333 if (rule.isHandling()) 334 { 335 Log.debug("handling {}",rule); 336 handled=true; 337 (request instanceof Request?(Request)request:HttpConnection.getCurrentConnection().getRequest()).setHandled(true); 338 } 339 340 if (rule.isTerminating()) 341 { 342 Log.debug("terminating {}",rule); 343 break; 344 } 345 } 346 } 347 348 if (!handled) 349 { 350 super.handle(target, request, response, dispatch); 351 } 352 } 353 } 354 355 }