Interface Handler

  • All Known Subinterfaces:
    RequestLogger, RequestTimingHandler
    All Known Implementing Classes:
    GroovyHandler, HealthCheckHandler, InjectionHandler, MetricsPrometheusHandler, MetricsWebsocketBroadcastHandler, ResponseTimer
    Functional Interface:
    This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

    @FunctionalInterface
    public interface Handler
    A handler participates in the processing of a request/response pair, operating on a Context.

    Handlers are the key component of Ratpack applications. A handler either generate a response, or delegate to another handler in some way.

    Non blocking/Asynchronous

    Handlers are expected to be asynchronous. That is, there is no expectation that the handler is “finished” when its handle(Context) method returns. This facilitates the use of non blocking IO without needing to enter some kind of special mode. An implication is that handlers must ensure that they either send a response or delegate to another handler.

    Handler pipeline

    Handlers are always part of a pipeline structure. The Context that the handler operates on provides the Context.next() method that passes control to the next handler in the pipeline. The last handler in the pipeline is always that generates a 404 client error.

    Handlers can themselves insert other handlers into the pipeline, using the Context.insert(Handler...) family of methods.

    Examples

    While there is no strict taxonomy of handlers, the following are indicative examples of common functions.
     import ratpack.core.handling.*;
    
     // A responder may just return a response to the client…
    
     class SimpleHandler implements Handler {
       void handle(Context exchange) {
         exchange.getResponse().send("Hello World!");
       }
     }
    
     // A responder may add a response header, before delegating to the next in the pipeline…
    
     class DecoratingHandler implements Handler {
       void handle(Context exchange) {
         exchange.getResponse().getHeaders().set("Cache-Control", "no-cache");
         exchange.next();
       }
     }
    
     // Or a handler may conditionally respond…
    
     class ConditionalHandler implements Handler {
       void handle(Context exchange) {
         if (exchange.getRequest().getPath().equals("foo")) {
           exchange.getResponse().send("Hello World!");
         } else {
           exchange.next();
         }
       }
     }
    
     // A handler does not need to participate in the response, but can instead "route" the exchange to different handlers…
    
     class RoutingHandler implements Handler {
       private final Handler[] fooHandlers;
    
       public RoutingHandler(Handler... fooHandlers) {
         this.fooHandlers = fooHandlers;
       }
    
       void handle(Context exchange) {
         if (exchange.getRequest().getPath().startsWith("foo/")) {
           exchange.insert(fooHandlers);
         } else {
           exchange.next();
         }
       }
     }
    
     // It can sometimes be appropriate to directly delegate to a handler, instead of using exchange.insert() …
    
     class FilteringHandler implements Handler {
       private final Handler nestedHandler;
    
       public FilteringHandler(Handler nestedHandler) {
         this.nestedHandler = nestedHandler;
       }
    
       void handle(Context exchange) {
         if (exchange.getRequest().getPath().startsWith("foo/")) {
           nestedHandler.handle(exchange);
         } else {
           exchange.next();
         }
       }
     }
     
    See Also:
    Handlers, Chain, Registry