ratpack.handling.Handlers Maven / Gradle / Ivy
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ratpack.handling;
import ratpack.api.Nullable;
import ratpack.file.FileHandlerSpec;
import ratpack.file.internal.DefaultFileHandlerSpec;
import ratpack.file.internal.FileSystemBindingHandler;
import ratpack.func.Action;
import ratpack.func.Predicate;
import ratpack.handling.internal.*;
import ratpack.path.PathBinder;
import ratpack.path.internal.PathHandler;
import ratpack.registry.Registry;
import ratpack.server.ServerConfig;
import java.util.List;
/**
* Factory methods for handler decorations.
*/
public abstract class Handlers {
private Handlers() {
}
/**
* A handler that delegates to the next handler if the request claims that it can accept one of the given types, otherwise raises a 406 client error.
*
* @param contentTypes The content types to verify that the request can support for the response
* @return A handler
*/
public static Handler accepts(String... contentTypes) {
return new AcceptsHandler(contentTypes);
}
/**
* Creates a handler that serves files from the file system.
*
* This method is a standalone version of {@link Chain#files(Action)}.
*
* @param serverConfig the server config
* @param config the configuration of the file handler
* @return a file serving handler
* @throws Exception any thrown by {@code config}
*/
public static Handler files(ServerConfig serverConfig, Action super FileHandlerSpec> config) throws Exception {
return DefaultFileHandlerSpec.build(serverConfig, config);
}
/**
* Builds a handler chain, with no backing registry.
*
* @param serverConfig The server config
* @param action The chain definition
* @return A handler
* @throws Exception any thrown by {@code action}
*/
public static Handler chain(ServerConfig serverConfig, Action super Chain> action) throws Exception {
return chain(serverConfig, null, action);
}
/**
* Builds a chain, backed by the given registry.
*
* @param serverConfig The server config
* @param registry The registry.
* @param action The chain building action.
* @return A handler
* @throws Exception any thrown by {@code action}
*/
public static Handler chain(@Nullable ServerConfig serverConfig, @Nullable Registry registry, Action super Chain> action) throws Exception {
return ChainBuilders.build(new ChainActionTransformer(serverConfig, registry), action);
}
/**
* Builds a chain, backed by the given registry.
*
* @param registry The registry.
* @param action The chain building action.
* @return A handler
* @throws Exception any thrown by {@code action}
*/
public static Handler chain(Registry registry, Action super Chain> action) throws Exception {
return chain(registry.get(ServerConfig.class), registry, action);
}
/**
* Creates a handler chain from the given handlers.
*
* @param handlers The handlers to connect into a chain
* @return A new handler that is the given handlers connected into a chain
*/
public static Handler chain(List extends Handler> handlers) {
if (handlers.size() == 0) {
return Context::next;
} else if (handlers.size() == 1) {
return handlers.get(0);
} else {
return new ChainHandler(handlers);
}
}
/**
* Creates a handler chain from the given handlers.
*
* @param handlers The handlers to connect into a chain
* @return A new handler that is the given handlers connected into a chain
*/
public static Handler chain(Handler... handlers) {
if (handlers.length == 0) {
return Handlers.next();
} else if (handlers.length == 1) {
return handlers[0];
} else {
return new ChainHandler(handlers);
}
}
/**
* A handler that simply calls {@link Context#clientError(int)} with the given status code.
*
* @param statusCode The 4xx client error status code
* @return A handler
*/
public static Handler clientError(int statusCode) {
return new ClientErrorForwardingHandler(statusCode);
}
/**
* A handler that delegates to the next handler if the content type of the request is one of the given types, otherwise raises a 415 client error.
*
* @param contentTypes The request content types to require
* @return A handler
*/
public static Handler contentTypes(String... contentTypes) {
return new ContentTypeHandler(contentTypes);
}
/**
* A handler that delegates to the next handler if the request is DELETE, otherwise raises a 405 client error.
*
* @return A handler
*/
public static Handler delete() {
return MethodHandler.DELETE;
}
/**
* A handlers that changes the {@link ratpack.file.FileSystemBinding} for the given handlers.
*
* The new file system binding will be created by the {@link ratpack.file.FileSystemBinding#binding(String)} method of the contextual binding.
*
* @param serverConfig The application server config
* @param path The relative path to the new file system binding point
* @param handler The handler to execute with the new file system binding
* @return A handler
*/
public static Handler fileSystem(ServerConfig serverConfig, String path, Handler handler) {
return new FileSystemBindingHandler(serverConfig, path, handler);
}
/**
* A handler that delegates to the next handler if the request is GET, otherwise raises a 405 client error.
*
* @return A handler
*/
public static Handler get() {
return MethodHandler.GET;
}
/**
* A handler that simply delegates to the next handler.
*
* Effectively a noop.
*
* @return A handler
*/
public static Handler next() {
return NextHandler.INSTANCE;
}
/**
* Convenience for {@link #clientError(int) clientError(404)}.
*
* @return A handler
*/
public static Handler notFound() {
return ClientErrorForwardingHandler.NOT_FOUND;
}
/**
* A handler that delegates to the next handler if the request is PATCH, otherwise raises a 405 client error.
*
* @return A handler
*/
public static Handler patch() {
return MethodHandler.PATCH;
}
/**
* Creates a handler that delegates to the given handlers if the request matches the given path exactly.
*
* The {@code path} is relative to the contextual {@link ratpack.path.PathBinding} of the exchange.
*
* A new contextual {@link ratpack.path.PathBinding} will be established for the given handlers,
* using the given path as the bind point.
*
* @param path The exact path to match to
* @param handler The handlers to delegate to if the path matches
* @return A handler
*/
public static Handler path(String path, Handler handler) {
return path(PathBinder.parse(path, true), handler);
}
/**
* Creates a handler that delegates to the given handlers if the request can be bound by the given path binder.
*
* @param pathBinder The path binder that may bind to the request path
* @param handler The handlers to delegate to if path binder does bind to the path
* @return A handler
*/
public static Handler path(PathBinder pathBinder, Handler handler) {
return new PathHandler(pathBinder, handler);
}
/**
* A handler that delegates to the next handler if the request is POST, otherwise raises a 405 client error.
*
* @return A handler
*/
public static Handler post() {
return MethodHandler.POST;
}
/**
* Creates a handler that delegates to the given handlers if the request path starts with the given prefix.
*
* The {@code prefix} is relative to the contextual {@link ratpack.path.PathBinding} of the exchange.
*
* A new contextual {@link ratpack.path.PathBinding} will be established for the given handlers,
* using the given prefix as the bind point.
*
* @param prefix The path prefix to match
* @param handler The handler to delegate to
* @return A handler
*/
public static Handler prefix(String prefix, Handler handler) {
return path(PathBinder.parse(prefix, false), handler);
}
/**
* A handler that delegates to the next handler if the request is PUT, otherwise raises a 405 client error.
*
* @return A handler
*/
public static Handler put() {
return MethodHandler.PUT;
}
/**
* A handler that simply calls {@link Context#insert(Registry, Handler...)} with the given registry and handler.
*
* @param registry the registry to insert
* @param handler The handler to insert
* @return A handler
*/
public static Handler register(Registry registry, Handler handler) {
return new RegistryInsertHandler(registry, handler);
}
/**
* A handler that simply calls {@link Context#next(Registry)} with the given registry.
*
* @param registry The registry to make available to the next handlers
* @return A handler
* @see Context#next(Registry)
*/
public static Handler register(Registry registry) {
return new RegistryNextHandler(registry);
}
/**
* Creates a handler that always issues a redirect using {@link Context#redirect(int, String)} with exactly the given code and location.
*
* This method will immediate throw an {@link IllegalArgumentException} if code is < 300 || > 399.
*
* @param code the 3XX HTTP status code
* @param location the URL to set in the Location response header
* @return a handler
* @see Context#redirect(int, String)
*/
public static Handler redirect(int code, String location) {
return new RedirectionHandler(location, code);
}
/**
* Creates a handler that inserts and delegates the given handler if the predicate applies to the context.
*
* If the predicate does not apply, calls {@link Context#next()}.
*
* @param test the test whether to when to the given handler
* @param handler the handler to insert if the predicate applies
* @return a handler
*/
public static Handler when(Predicate super Context> test, Handler handler) {
return new WhenHandler(test, handler);
}
/**
* Creates a handler that delegates to the given handler if the predicate applies to the context.
*
* If the predicate does not apply, calls {@link Context#next()}.
*
* This method does not {@link Context#insert(Handler...) insert} the handler as {@link #when(Predicate, Handler)} does;
* it calls its {@link Handler#handle(Context)} method directly
*
* @param test the test whether to when to the given handler
* @param handler the handler to call if the predicate applies
* @return a handler
*/
public static Handler onlyIf(Predicate super Context> test, Handler handler) {
return new OnlyIfHandler(test, handler);
}
}