netflix.karyon.transport.http.SimpleUriRouter Maven / Gradle / Ivy
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;
}
}
}