Class ConditionalHandler

java.lang.Object
org.eclipse.jetty.util.component.AbstractLifeCycle
org.eclipse.jetty.util.component.ContainerLifeCycle
All Implemented Interfaces:
Handler, Handler.Container, Handler.Singleton, Request.Handler, org.eclipse.jetty.util.component.Container, org.eclipse.jetty.util.component.Destroyable, org.eclipse.jetty.util.component.Dumpable, org.eclipse.jetty.util.component.Dumpable.DumpableContainer, org.eclipse.jetty.util.component.LifeCycle, org.eclipse.jetty.util.thread.Invocable
Direct Known Subclasses:
ConditionalHandler.Abstract, ConditionalHandler.ElseNext

public abstract class ConditionalHandler extends Handler.Wrapper
A Handler.Wrapper that conditionally handles a Request. The conditions are implemented by IncludeExcludes of:
  • A HTTP method name, which can be efficiently matched
  • A PathSpec or string representation, which can be efficiently matched.
  • An arbitrary Predicate taking the Request, which is matched in a linear test of all predicates.

If the conditions are met, the abstract onConditionsMet(Request, Response, Callback) method will be invoked, otherwise the onConditionsNotMet(Request, Response, Callback) method will be invoked. Implementations may call the nextHandler(Request, Response, Callback) method to call the wrapped handler.

A typical usage is to extend the ConditionalHandler.Abstract sub class and provide an implementation of onConditionsMet(Request, Response, Callback) and onConditionsNotMet(Request, Response, Callback):


 public class MyOptionalHandler extends ConditionalHandler.Abstract
 {
     @Override
     public boolean onConditionsMet(Request request, Response response, Callback callback)
     {
         response.getHeaders().add("Test", "My Optional Handling");
         return nextHandle(request, response, callback);
     }

     @Override
     public boolean onConditionsNoMet(Request request, Response response, Callback callback)
     {
         return false;
     }
 }
 

If the conditions added to MyOptionalHandler are met, then the onConditionsMet(Request, Response, Callback) method is called and a response header added before invoking nextHandler(Request, Response, Callback), otherwise the onConditionsNotMet(Request, Response, Callback) is called, which returns false to indicate no more handling.

Alternatively, one of the concrete subclasses may be used. These implementations conditionally provide a specific action in their onConditionsMet(Request, Response, Callback) methods:

Otherwise, if their conditions are not met, these subclasses are all extension of the abstract ConditionalHandler.ElseNext subclass, that implements onConditionsNotMet(Request, Response, Callback) to call nextHandler(Request, Response, Callback). Thus their specific behaviour is not applied and the handling continues with the next handler.

These concrete handlers are ideal for retrofitting conditional behavior. For example, if an application handler was found to not correctly handle the OPTIONS method for the path "/secret/*", it could be protected as follows:


    Server server = new Server();
    ApplicationHandler application = new ApplicationHandler();
    server.setHandler(application);

    ConditionalHandler reject = new ConditionalHandler.Reject(403); // or DontHandle
    reject.includeMethod("OPTIONS");
    reject.includePath("/secret/*");
    server.insertHandler(reject);
 

Another example, in an application comprised of several handlers, one of which is a wrapping handler whose behavior needs to be skipped for "POST" requests, then it could be achieved as follows:


    Server server = new Server();
    ApplicationWrappingHandler wrappingHandler = new ApplicationWrappingHandler();
    ApplicationHandler applicationHandler = new ApplicationHandler();
    server.setHandler(wrappingHandler);
    filter.setHandler(applicationHandler);

    ConditionalHandler skipNext = new ConditionalHandler.SkipNext();
    skipNext.includeMethod("POST");
    skipNext.setHandler(wrappingHandler);
    server.setHandler(skipNext);
 

Note that a better solution, if possible, would be for the ApplicationFilterHandler and/or ApplicationHandler handlers to extend ConditionalHandler.

  • Method Details

    • clear

      public void clear()
      Clear all inclusions and exclusions.
    • includeMethod

      public void includeMethod(String... methods)
      Include methods in the conditions to be met
      Parameters:
      methods - The exact case-sensitive method name
    • excludeMethod

      public void excludeMethod(String... methods)
      Exclude methods in the conditions to be met
      Parameters:
      methods - The exact case-sensitive method name
    • include

      public void include(org.eclipse.jetty.http.pathmap.PathSpec... paths)
      Include PathSpecs in the conditions to be met
      Parameters:
      paths - The PathSpecs that are tested against the pathInContext.
    • exclude

      public void exclude(org.eclipse.jetty.http.pathmap.PathSpec... paths)
      Exclude PathSpecs in the conditions to be met
      Parameters:
      paths - The PathSpecs that are tested against the pathInContext.
    • includePath

      public void includePath(String... paths)
      Include PathSpecs in the conditions to be met
      Parameters:
      paths - String representations of PathSpecs that are tested against the pathInContext.
    • excludePath

      public void excludePath(String... paths)
      Exclude PathSpec in the conditions to be met
      Parameters:
      paths - String representations of PathSpecs that are tested against the pathInContext.
    • include

      public void include(org.eclipse.jetty.util.InetAddressPattern... patterns)
      Include InetAddressPatterns in the conditions to be met
      Parameters:
      patterns - InetAddressPatterns that are tested against the getRemoteSocketAddress() of Request.getConnectionMetaData().
    • includeInetAddressPattern

      public void includeInetAddressPattern(String... patterns)
      Include InetAddressPatterns in the conditions to be met
      Parameters:
      patterns - String representations of InetAddressPatterns that are tested against the getRemoteSocketAddress() of Request.getConnectionMetaData().
    • exclude

      public void exclude(org.eclipse.jetty.util.InetAddressPattern... patterns)
      Exclude InetAddressPatterns in the conditions to be met
      Parameters:
      patterns - InetAddressPatterns that are tested against the getRemoteSocketAddress() of Request.getConnectionMetaData().
    • excludeInetAddressPattern

      public void excludeInetAddressPattern(String... patterns)
      Exclude InetAddressPattern in the conditions to be met
      Parameters:
      patterns - String representations of InetAddressPatterns that are tested against the getRemoteSocketAddress() of Request.getConnectionMetaData().
    • include

      @SafeVarargs public final void include(Predicate<Request>... predicates)
      Include arbitrary Predicates in the conditions.
      Parameters:
      predicates - Predicates that are tested against the Request. This method is optimized so that a passed ConditionalHandler.MethodPredicate or ConditionalHandler.PathSpecPredicate is converted to a more efficient includeMethod(String...) or include(PathSpec...) respectively.
    • exclude

      @SafeVarargs public final void exclude(Predicate<Request>... predicates)
      Exclude arbitrary Predicates in the conditions.
      Parameters:
      predicates - Predicates that are tested against the Request. This method is optimized so that a passed ConditionalHandler.MethodPredicate or ConditionalHandler.PathSpecPredicate is converted to a more efficient excludeMethod(String...) or exclude(PathSpec...) respectively.
    • doStart

      protected void doStart() throws Exception
      Overrides:
      doStart in class Handler.Abstract
      Throws:
      Exception
    • handle

      public final boolean handle(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
      Description copied from interface: Request.Handler

      Invoked to handle the passed HTTP request and response.

      The request is accepted by returning true, then handling must be concluded by completing the passed callback. The handling may be asynchronous, i.e. this method may return true and complete the given callback later, possibly from a different thread. If this method returns false, then the callback must not be invoked and any mutation on the response reversed.

      Exceptions thrown by this method may be subsequently handled by an error Request.Handler, if present, otherwise a default HTTP 500 error is generated and the callback completed while writing the error response.

      The simplest implementation is:

       public boolean handle(Request request, Response response, Callback callback)
       {
           callback.succeeded();
           return true;
       }
       

      A HelloWorld implementation is:

       public boolean handle(Request request, Response response, Callback callback)
       {
           response.write(true, ByteBuffer.wrap("Hello World\n".getBytes(StandardCharsets.UTF_8)), callback);
           return true;
       }
       
      Specified by:
      handle in interface Request.Handler
      Overrides:
      handle in class Handler.Wrapper
      Parameters:
      request - the HTTP request to handle
      response - the HTTP response to handle
      callback - the callback to complete when the handling is complete
      Returns:
      True if and only if the request will be handled, a response generated and the callback eventually called. This may occur within the scope of the call to this method, or asynchronously some time later. If false is returned, then this method must not generate a response, nor complete the callback.
      Throws:
      Exception - if there is a failure during the handling. Catchers cannot assume that the callback will be called and thus should attempt to complete the request as if a false had been returned.
    • onConditionsMet

      protected abstract boolean onConditionsMet(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
      Handle a request that has met the conditions. Typically, the implementation will provide optional handling and then call the nextHandler(Request, Response, Callback) method to continue handling.
      Parameters:
      request - The request to handle
      response - The response to generate
      callback - The callback for completion
      Returns:
      True if this handler will complete the callback
      Throws:
      Exception - If there is a problem handling
      See Also:
    • onConditionsNotMet

      protected abstract boolean onConditionsNotMet(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
      This method is called when the request has not met the conditions and is not to be handled by this handler. Implementations may return false; send an error response; or handle the request differently.
      Parameters:
      request - The request to handle
      response - The response to generate
      callback - The callback for completion
      Returns:
      True if this handler will complete the callback
      Throws:
      Exception - If there is a problem handling
      See Also:
    • nextHandler

      protected boolean nextHandler(Request request, Response response, org.eclipse.jetty.util.Callback callback) throws Exception
      Handle a request by invoking the handle(Request, Response, Callback) method of the next Handler.
      Parameters:
      request - The request to handle
      response - The response to generate
      callback - The callback for completion
      Returns:
      True if this handler will complete the callback
      Throws:
      Exception - If there is a problem handling
      See Also:
    • dump

      public void dump(Appendable out, String indent) throws IOException
      Specified by:
      dump in interface org.eclipse.jetty.util.component.Dumpable
      Overrides:
      dump in class org.eclipse.jetty.util.component.ContainerLifeCycle
      Throws:
      IOException
    • from

      public static Predicate<Request> from(String connectorName, String inetAddressPattern, String method, String pathSpec)
      Parameters:
      connectorName - The connector name or null
      inetAddressPattern - An InetAddressPattern string or null
      method - A HttpMethod name or null
      pathSpec - A PathSpec string or null
      Returns:
      the combined Predicate over Request
    • from

      public static Predicate<Request> from(String connectorName, org.eclipse.jetty.util.InetAddressPattern inetAddressPattern, String method, org.eclipse.jetty.http.pathmap.PathSpec pathSpec)
      Parameters:
      connectorName - The connector name or null
      inetAddressPattern - An InetAddressPattern or null
      method - A HttpMethod name or null
      pathSpec - A PathSpec or null
      Returns:
      the combined Predicate over Request