Defensive checks in WebClient and Reactor connector

Since there is no reason for an exchange to ever complete without a
ClientResponse I've added a switchIfEmpty check at the WebClient level.

Also, temporarily a second check closer to the problem in the
ReactorClientHttpConnector suggesting a workaround and providing a
reference to the Reactor Netty issue #138.

Issue: SPR-15784
This commit is contained in:
Rossen Stoyanchev
2017-07-18 18:13:47 +02:00
parent 56903581d9
commit 43f2de4671
3 changed files with 42 additions and 8 deletions

View File

@@ -23,6 +23,8 @@ import java.util.function.Function;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.http.client.HttpClient;
import reactor.ipc.netty.http.client.HttpClientOptions;
import reactor.ipc.netty.http.client.HttpClientRequest;
import reactor.ipc.netty.http.client.HttpClientResponse;
import reactor.ipc.netty.options.ClientOptions;
import org.springframework.http.HttpMethod;
@@ -36,6 +38,12 @@ import org.springframework.http.HttpMethod;
*/
public class ReactorClientHttpConnector implements ClientHttpConnector {
private static final Mono<ClientHttpResponse> NO_CLIENT_RESPONSE_ERROR = Mono.error(
new IllegalStateException("HttpClient completed without a response. " +
"As a temporary workaround try to disable connection pool. " +
"See https://github.com/reactor/reactor-netty/issues/138."));
private final HttpClient httpClient;
@@ -61,11 +69,23 @@ public class ReactorClientHttpConnector implements ClientHttpConnector {
Function<? super ClientHttpRequest, Mono<Void>> requestCallback) {
return this.httpClient
.request(io.netty.handler.codec.http.HttpMethod.valueOf(method.name()),
.request(adaptHttpMethod(method),
uri.toString(),
httpClientRequest -> requestCallback
.apply(new ReactorClientHttpRequest(method, uri, httpClientRequest)))
.map(ReactorClientHttpResponse::new);
request -> requestCallback.apply(adaptRequest(method, uri, request)))
.map(this::adaptResponse)
.switchIfEmpty(NO_CLIENT_RESPONSE_ERROR);
}
private io.netty.handler.codec.http.HttpMethod adaptHttpMethod(HttpMethod method) {
return io.netty.handler.codec.http.HttpMethod.valueOf(method.name());
}
private ReactorClientHttpRequest adaptRequest(HttpMethod method, URI uri, HttpClientRequest request) {
return new ReactorClientHttpRequest(method, uri, request);
}
private ClientHttpResponse adaptResponse(HttpClientResponse response) {
return new ReactorClientHttpResponse(response);
}
}