| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.rewrite.handler; |
| |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.EnumSet; |
| |
| import javax.servlet.DispatcherType; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.handler.HandlerWrapper; |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| *<p> Rewrite handler is responsible for managing the rules. Its capabilities |
| * is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule. |
| * There is also handling for cookies, headers, redirection, setting status or error codes |
| * whenever the rule finds a match. |
| * |
| * <p> The rules can be matched by the either: pattern matching of PathMap |
| * (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set |
| * (eg {@link MsieSslRule} - the requests must be in SSL mode). |
| * |
| * <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only |
| * be applied if the request matches the conditions for their container |
| * (e.g., by virtual host name) |
| * |
| * <p>The list of predefined rules is: |
| * <ul> |
| * <li> {@link CookiePatternRule} - adds a new cookie in response. </li> |
| * <li> {@link HeaderPatternRule} - adds/modifies the HTTP headers in response. </li> |
| * <li> {@link RedirectPatternRule} - sets the redirect location. </li> |
| * <li> {@link ResponsePatternRule} - sets the status/error codes. </li> |
| * <li> {@link RewritePatternRule} - rewrites the requested URI. </li> |
| * <li> {@link RewriteRegexRule} - rewrites the requested URI using regular expression for pattern matching. </li> |
| * <li> {@link MsieSslRule} - disables the keep alive on SSL for IE5 and IE6. </li> |
| * <li> {@link ForwardedSchemeHeaderRule} - set the scheme according to the headers present. </li> |
| * <li> {@link VirtualHostRuleContainer} - checks whether the request matches one of a set of virtual host names.</li> |
| * </ul> |
| * |
| * |
| * Here is a typical jetty.xml configuration would be: <pre> |
| * |
| * <New id="RewriteHandler" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"> |
| * <Set name="rules"> |
| * <Array type="org.eclipse.jetty.rewrite.handler.Rule"> |
| * |
| * <Item> |
| * <New id="rewrite" class="org.eclipse.jetty.rewrite.handler.RewritePatternRule"> |
| * <Set name="pattern">/*</Set> |
| * <Set name="replacement">/test</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule"> |
| * <Set name="pattern">/session/</Set> |
| * <Set name="code">400</Set> |
| * <Set name="reason">Setting error code 400</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> |
| * <Set name="pattern">*.jsp</Set> |
| * <Set name="name">server</Set> |
| * <Set name="value">dexter webserver</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> |
| * <Set name="pattern">*.jsp</Set> |
| * <Set name="name">title</Set> |
| * <Set name="value">driven header purpose</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule"> |
| * <Set name="pattern">/test/dispatch</Set> |
| * <Set name="location">http://jetty.eclipse.org</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule"> |
| * <Set name="regex">/test-jaas/$</Set> |
| * <Set name="replacement">/demo</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="forwardedHttps" class="org.eclipse.jetty.rewrite.handler.ForwardedSchemeHeaderRule"> |
| * <Set name="header">X-Forwarded-Scheme</Set> |
| * <Set name="headerValue">https</Set> |
| * <Set name="scheme">https</Set> |
| * </New> |
| * </Item> |
| * |
| * <Item> |
| * <New id="virtualHost" class="org.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer"> |
| * |
| * <Set name="virtualHosts"> |
| * <Array type="java.lang.String"> |
| * <Item>eclipse.com</Item> |
| * <Item>www.eclipse.com</Item> |
| * <Item>eclipse.org</Item> |
| * <Item>www.eclipse.org</Item> |
| * </Array> |
| * </Set> |
| * |
| * <Call name="addRule"> |
| * <Arg> |
| * <New class="org.eclipse.jetty.rewrite.handler.CookiePatternRule"> |
| * <Set name="pattern">/*</Set> |
| * <Set name="name">CookiePatternRule</Set> |
| * <Set name="value">1</Set> |
| * </New> |
| * </Arg> |
| * </Call> |
| * |
| * </New> |
| * </Item> |
| * |
| * </Array> |
| * </Set> |
| * </New> |
| * |
| * <Set name="handler"> |
| * <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> |
| * <Set name="handlers"> |
| * <Array type="org.eclipse.jetty.server.Handler"> |
| * <Item> |
| * <Ref id="RewriteHandler"/> |
| * </Item> |
| * <Item> |
| * <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/> |
| * </Item> |
| * <Item> |
| * <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/> |
| * </Item> |
| * <Item> |
| * <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/> |
| * </Item> |
| * </Array> |
| * </Set> |
| * </New> |
| * </Set> |
| * </pre> |
| * |
| */ |
| public class RewriteHandler extends HandlerWrapper |
| { |
| private RuleContainer _rules; |
| private EnumSet<DispatcherType> _dispatchTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC); |
| |
| /* ------------------------------------------------------------ */ |
| public RewriteHandler() |
| { |
| _rules = new RuleContainer(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Returns the list of rules. |
| * @return an array of {@link Rule}. |
| */ |
| public Rule[] getRules() |
| { |
| return _rules.getRules(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Assigns the rules to process. |
| * @param rules an array of {@link Rule}. |
| */ |
| public void setRules(Rule[] rules) |
| { |
| _rules.setRules(rules); |
| } |
| |
| /*------------------------------------------------------------ */ |
| /** |
| * Assigns the rules to process. |
| * @param rules a {@link RuleContainer} containing other rules to process |
| */ |
| @Deprecated |
| public void setRules(RuleContainer rules) |
| { |
| _rules = rules; |
| } |
| |
| /*------------------------------------------------------------ */ |
| /** |
| * Assigns the rules to process. |
| * @param rules a {@link RuleContainer} containing other rules to process |
| */ |
| public void setRuleContainer(RuleContainer rules) |
| { |
| _rules = rules; |
| } |
| |
| /*------------------------------------------------------------ */ |
| public RuleContainer getRuleContainer() |
| { |
| return _rules; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * Add a Rule |
| * @param rule The rule to add to the end of the rules array |
| */ |
| public void addRule(Rule rule) |
| { |
| _rules.addRule(rule); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return the rewriteRequestURI If true, this handler will rewrite the value |
| * returned by {@link HttpServletRequest#getRequestURI()}. |
| */ |
| public boolean isRewriteRequestURI() |
| { |
| return _rules.isRewriteRequestURI(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param rewriteRequestURI true if this handler will rewrite the value |
| * returned by {@link HttpServletRequest#getRequestURI()}. |
| */ |
| public void setRewriteRequestURI(boolean rewriteRequestURI) |
| { |
| _rules.setRewriteRequestURI(rewriteRequestURI); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return true if this handler will rewrite the value |
| * returned by {@link HttpServletRequest#getPathInfo()}. |
| */ |
| public boolean isRewritePathInfo() |
| { |
| return _rules.isRewritePathInfo(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param rewritePathInfo true if this handler will rewrite the value |
| * returned by {@link HttpServletRequest#getPathInfo()}. |
| */ |
| public void setRewritePathInfo(boolean rewritePathInfo) |
| { |
| _rules.setRewritePathInfo(rewritePathInfo); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @return the originalPathAttribte. If non null, this string will be used |
| * as the attribute name to store the original request path. |
| */ |
| public String getOriginalPathAttribute() |
| { |
| return _rules.getOriginalPathAttribute(); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /** |
| * @param originalPathAttribute If non null, this string will be used |
| * as the attribute name to store the original request path. |
| */ |
| public void setOriginalPathAttribute(String originalPathAttribute) |
| { |
| _rules.setOriginalPathAttribute(originalPathAttribute); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public EnumSet<DispatcherType> getDispatcherTypes() |
| { |
| return _dispatchTypes; |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void setDispatcherTypes(EnumSet<DispatcherType> types) |
| { |
| _dispatchTypes=EnumSet.copyOf(types); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| public void setDispatcherTypes(DispatcherType... types) |
| { |
| _dispatchTypes=EnumSet.copyOf(Arrays.asList(types)); |
| } |
| |
| /* ------------------------------------------------------------ */ |
| /* (non-Javadoc) |
| * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) |
| */ |
| @Override |
| public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException |
| { |
| if (isStarted()) |
| { |
| if (_dispatchTypes.contains(baseRequest.getDispatcherType())) |
| { |
| String returned = _rules.matchAndApply(target, request, response); |
| target = (returned == null) ? target : returned; |
| } |
| |
| if (!baseRequest.isHandled()) |
| super.handle(target, baseRequest, request, response); |
| } |
| } |
| |
| } |