All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sirius.web.http.WebDispatcher Maven / Gradle / Ivy

There is a newer version: 22.2.3
Show newest version
/*
 * Made with all the love in the world
 * by scireum in Remshalden, Germany
 *
 * Copyright by scireum GmbH
 * http://www.scireum.de - [email protected]
 */

package sirius.web.http;

import sirius.kernel.commons.Callback;
import sirius.kernel.di.std.Priorized;

import java.util.function.Consumer;

/**
 * Participates in the dispatching process for incoming HTTP requests.
 * 

* Once a HTTP request is fully read by the server it is dispatched calling all available WebDispatcher * instances available. To provide a WebDispatcher, a subclass therefore needs to wear an * {@link sirius.kernel.di.std.Register} annotation. *

* As the first request arrives, all dispatchers are asked for their priority (via {@link #getPriority()} and * then sorted according to that in an ascending manner. As default priority * {@link sirius.kernel.commons.PriorityCollector#DEFAULT_PRIORITY} can be used. Note that this will only be done * once, therefore getPriority() must only return a constant value as it is never re-evaluated. By default, * a not found handler ({@link sirius.web.dispatch.DefaultDispatcher} is registered with 999 as priority, so higher * priorities will never be executed. *

* For each incoming request, the list of dispatchers is iterated and {@link #dispatch(WebContext)} is invoked * until one of those returns true, to signal that the request was handled. *

* The dispatchers are invoked in a separate thread so that blocking operations will not block the web-server itself. *

* If a dispatcher is willing to handle all incoming data (payload of a PUT or POST request) by itself - instead of * just accumulating this data in memory or on disk, the {@link #preparePreDispatch(WebContext)} method must return * an appropriate handler for a given request. This needs to install a {@link ContentHandler}. Note that no further * {@link #dispatch(WebContext)} will be called for a request which received a true for its call * to {@link #preparePreDispatch(WebContext)}. *

* Note that {@link #preparePreDispatch(WebContext)} will be invoked within the event loop of the web-server, therefore * absolutely no blocking operations must be performed. However, the returned Callback is executed in its own * thread and free of any constraints. *

* * @see WebServerHandler */ public interface WebDispatcher extends Priorized { /** * Returns the priority to determine the position in the dispatcher list. *

* Dispatchers are sorted ascending (lower is better). The default priority is * {@link sirius.kernel.commons.PriorityCollector#DEFAULT_PRIORITY}, the max. value is 998 as everything above * will be handled by the {@link sirius.web.dispatch.DefaultDispatcher}. * * @return the priority of the dispatcher */ @Override int getPriority(); /** * Invoked as soon as the complete request but not its contents are available. *

* In contrast to {@link #dispatch(WebContext)} this method is invoked before the complete data is accumulated. * This permits the handler to install an {@link ContentHandler} using {@link WebContext#setContentHandler(ContentHandler)} * in order to directly process the uploaded data. A request for which true was replied will not * be dispatched again once it is complete. *

* Note thatthis method will be invoked within the event loop of the web-server, therefore absolutely no blocking * operations must be performed. However, the returned Callback is executed in its own thread and free of * any constraints. * * @param ctx the request to handle * @return the handler which will install the ContentHandler and eventually process the request or * null to indicate that no pre-dispatching is possible. * @see sirius.web.controller.ControllerDispatcher#preparePreDispatch(WebContext) */ default Callback preparePreDispatch(WebContext ctx) { return null; } /** * Invoked in order to handle the given request. *

* If the dispatcher doesn't feel responsible for handling the request, it simply invokes nextStage. *

* Note that no blocking operation must be performed in this method. For any complex interaction, a new thread * should be forked using {@link sirius.kernel.async.Tasks#executor(String)}. Note that even * {@link Response#outputStream(io.netty.handler.codec.http.HttpResponseStatus, String)} might * block sooner or later to limit heap memory usage - so fork a thread for any serious work besides checking * responsibilities for handling requests. * * @param ctx the request to handle * @param startOfPipeline the start of the pipeline in order * @param nextStage the next stage to forward the request to in case the dispatcher isn't interested * @throws Exception in case of an error when parsing or dispatching the request */ default void dispatch(WebContext ctx, Consumer startOfPipeline, Consumer nextStage) throws Exception { if (!dispatch(ctx)) { nextStage.accept(ctx); } } /** * Invoked in order to handle the given request. *

* If the dispatcher doesn't feel responsible for handling the request, it simply returns false. Otherwise * if the request is being handled, true must be returned *

* Note that no blocking operation must be performed in this method. For any complex interaction, a new thread * should be forked using {@link sirius.kernel.async.Tasks#executor(String)}. Note that even * {@link Response#outputStream(io.netty.handler.codec.http.HttpResponseStatus, String)} might * block sooner or later to limit heap memory usage - so fork a thread for any serious work besides checking * responsibilities for handling requests. * * @param ctx the request to handle * @return true if the request was handled by this dispatcher, false otherwise. * @throws Exception in case of an error when parsing or dispatching the request */ boolean dispatch(WebContext ctx) throws Exception; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy