package org.zalando.riptide.problem;
import org.springframework.http.MediaType;
import org.zalando.fauxpas.ThrowingConsumer;
import org.zalando.problem.Exceptional;
import org.zalando.problem.Problem;
import org.zalando.riptide.Navigators;
import org.zalando.riptide.Route;
import static org.springframework.http.MediaType.parseMediaType;
import static org.zalando.riptide.Bindings.on;
import static org.zalando.riptide.Navigators.contentType;
import static org.zalando.riptide.RoutingTree.dispatch;
public final class ProblemRoute {
private static final MediaType PROBLEM = parseMediaType("application/problem+json");
/**
* @see <a href="http://zalando.github.io/restful-api-guidelines/common-data-objects/CommonDataObjects.html#must-use-problem-json">Zalando RESTful API Guidelines</a>
*/
private static final MediaType X_DOT_PROBLEM = parseMediaType("application/x.problem+json");
/**
* Alternative spelling for {@link #X_DOT_PROBLEM}.
*/
private static final MediaType X_DASH_PROBLEM = parseMediaType("application/x-problem+json");
private static final Route PROPAGATE = problemHandling(Exceptional::propagate);
ProblemRoute() {
// package private so we can trick code coverage
}
/**
* Produces a {@link Route route} that dispatches on the {@link Navigators#contentType() content type} and
* recognises {@code application/problem+json} as well as {@code application/x-problem+json} and
* {@code application/x.problem+json} as {@link Problem problems} and {@link Exceptional#propagate() propagates}
* them.
*
* @see #problemHandling(ThrowingConsumer)
* @see Exceptional#propagate()
* @return static route for handling problems by propagating them as exceptions
*/
public static Route problemHandling() {
return PROPAGATE;
}
/**
* Produces a {@link Route route} that dispatches on the {@link Navigators#contentType() content type} and
* recognises {@code application/problem+json} as well as {@code application/x-problem+json} and
* {@code application/x.problem+json} as {@link Problem problems} and handles them given the supplied consumer.
*
* @param consumer the exception handler
* @return a route for handling problems dynamically
*/
public static Route problemHandling(final ThrowingConsumer<Exceptional, ? extends Exception> consumer) {
final Route route = Route.call(Exceptional.class, consumer);
return dispatch(contentType(),
on(PROBLEM).call(route),
on(X_DOT_PROBLEM).call(route),
on(X_DASH_PROBLEM).call(route));
}
}