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

netflix.karyon.transport.http.SimpleUriRouter Maven / Gradle / Ivy

There is a newer version: 2.9.2
Show newest version
package netflix.karyon.transport.http;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.reactivex.netty.protocol.http.server.HttpServerRequest;
import io.reactivex.netty.protocol.http.server.HttpServerResponse;
import io.reactivex.netty.protocol.http.server.RequestHandler;
import netflix.karyon.transport.interceptor.InterceptorKey;
import rx.Observable;

import java.util.concurrent.CopyOnWriteArrayList;

/**
 * A simple implementation for handling requests for different URIs. This router provides a facility to update the
 * routes at runtime. Thread-safety is maintained by using a "copy-on-write" data structure underneath, hence it comes
 * with an object allocation cost.
 *
 * The correct way to use this router would be to create all the routes at startup and then do not update the routes
 * at runtime unless it is required.
 *
 * @author Nitesh Kant
 */
public class SimpleUriRouter implements RequestHandler {

    private final CopyOnWriteArrayList routes;

    public SimpleUriRouter() {
        routes = new CopyOnWriteArrayList();
    }

    @Override
    public Observable handle(HttpServerRequest request, HttpServerResponse response) {
        HttpKeyEvaluationContext context = new HttpKeyEvaluationContext(response.getChannel());
        for (Route route : routes) {
            if (route.key.apply(request, context)) {
                return route.getHandler().handle(request, response);
            }
        }

        // None of the routes matched.
        response.setStatus(HttpResponseStatus.NOT_FOUND);
        return response.close();
    }

    /**
     * Add a new URI -< Handler route to this router.
     * @param uri URI to match.
     * @param handler Request handler.
     * @return The updated router.
     */
    public SimpleUriRouter addUri(String uri, RequestHandler handler) {
        routes.add(new Route(new ServletStyleUriConstraintKey(uri, ""), handler));
        return this;
    }

    /**
     * Add a new URI regex -< Handler route to this router.
     * @param uriRegEx URI regex to match
     * @param handler Request handler.
     * @return The updated router.
     */
    public SimpleUriRouter addUriRegex(String uriRegEx, RequestHandler handler) {
        routes.add(new Route(new RegexUriConstraintKey(uriRegEx), handler));
        return this;
    }

    private class Route {

        private final InterceptorKey, HttpKeyEvaluationContext> key;
        private final RequestHandler handler;

        public Route(InterceptorKey, HttpKeyEvaluationContext> key,
                      RequestHandler handler) {
            this.key = key;
            this.handler = handler;
        }

        public InterceptorKey, HttpKeyEvaluationContext> getKey() {
            return key;
        }

        public RequestHandler getHandler() {
            return handler;
        }
    }
}