Class ConditionalHandler

All Implemented Interfaces:
Handler, Handler.Container, Handler.Singleton, Request.Handler, Container, Destroyable, Dumpable, Dumpable.DumpableContainer, LifeCycle, 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.