Add HttpExceptionHandler

This commit is contained in:
Rossen Stoyanchev
2015-12-09 14:44:05 -05:00
parent 448aac813a
commit 4ba3d0736f
4 changed files with 300 additions and 38 deletions
@@ -0,0 +1,73 @@
/*
* Copyright 2002-2015 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 org.springframework.http.server.reactive;
import java.util.Arrays;
import java.util.List;
import org.reactivestreams.Publisher;
import reactor.Publishers;
import reactor.core.publisher.convert.RxJava1Converter;
import rx.Observable;
import org.springframework.util.Assert;
/**
* {@link HttpHandler} that delegates to a target {@link HttpHandler} and handles
* any errors from it by invoking one or more {@link HttpExceptionHandler}s
* sequentially until one of them completes successfully.
*
* @author Rossen Stoyanchev
*/
public class ErrorHandlingHttpHandler extends HttpHandlerDecorator {
private final List<HttpExceptionHandler> exceptionHandlers;
public ErrorHandlingHttpHandler(HttpHandler targetHandler, HttpExceptionHandler... exceptionHandlers) {
super(targetHandler);
Assert.notEmpty(exceptionHandlers, "At least one exception handler is required");
this.exceptionHandlers = Arrays.asList(exceptionHandlers);
}
@Override
public Publisher<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
Publisher<Void> publisher;
try {
publisher = getDelegate().handle(request, response);
}
catch (Throwable ex) {
publisher = Publishers.error(ex);
}
for (HttpExceptionHandler handler : this.exceptionHandlers) {
publisher = applyExceptionHandler(publisher, handler, request, response);
}
return publisher;
}
private static Publisher<Void> applyExceptionHandler(Publisher<Void> publisher,
HttpExceptionHandler handler, ServerHttpRequest request, ServerHttpResponse response) {
// see https://github.com/reactor/reactor/issues/580
Observable<Void> observable = RxJava1Converter.from(publisher).onErrorResumeNext(ex -> {
return RxJava1Converter.from(handler.handle(request, response, ex));
});
return RxJava1Converter.from(observable);
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2002-2015 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 org.springframework.http.server.reactive;
import org.reactivestreams.Publisher;
/**
* A contract for resolving exceptions from HTTP request handling.
*
* <p>{@link ErrorHandlingHttpHandler} provides a way of applying a list
* {@link HttpExceptionHandler}s to a target {@link HttpHandler}.
*
* @author Rossen Stoyanchev
* @see ErrorHandlingHttpHandler
*/
public interface HttpExceptionHandler {
/**
* Handle the given exception and return a completion Publisher to indicate
* when error handling is complete, or send an error signal if the exception
* was not handled.
*
* @param request the current request
* @param response the current response
* @param ex the exception to handle
* @return Publisher to indicate when exception handling is complete.
*/
Publisher<Void> handle(ServerHttpRequest request, ServerHttpResponse response, Throwable ex);
}