Upgrade to Reactor Netty 0.8

Issue: SPR-16387
This commit is contained in:
Violeta Georgieva
2018-05-17 21:47:18 +03:00
committed by Rossen Stoyanchev
parent 61ffbe5554
commit ffbc75ae47
20 changed files with 144 additions and 178 deletions

View File

@@ -17,24 +17,25 @@
package org.springframework.http.client.reactive;
import java.net.URI;
import java.util.function.Consumer;
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 reactor.netty.NettyInbound;
import reactor.netty.NettyOutbound;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClientRequest;
import reactor.netty.http.client.HttpClientResponse;
import org.springframework.http.HttpMethod;
import io.netty.buffer.ByteBufAllocator;
/**
* Reactor-Netty implementation of {@link ClientHttpConnector}.
*
* @author Brian Clozel
* @since 5.0
* @see reactor.ipc.netty.http.client.HttpClient
* @see reactor.netty.http.client.HttpClient
*/
public class ReactorClientHttpConnector implements ClientHttpConnector {
@@ -43,20 +44,19 @@ public class ReactorClientHttpConnector implements ClientHttpConnector {
/**
* Create a Reactor Netty {@link ClientHttpConnector}
* with default {@link ClientOptions} and HTTP compression support enabled.
* with a default configuration and HTTP compression support enabled.
*/
public ReactorClientHttpConnector() {
this.httpClient = HttpClient.builder()
.options(options -> options.compression(true))
.build();
this.httpClient = HttpClient.create()
.compress();
}
/**
* Create a Reactor Netty {@link ClientHttpConnector} with the given
* {@link HttpClientOptions.Builder}
* {@link HttpClient}
*/
public ReactorClientHttpConnector(Consumer<? super HttpClientOptions.Builder> clientOptions) {
this.httpClient = HttpClient.create(clientOptions);
public ReactorClientHttpConnector(HttpClient httpClient) {
this.httpClient = httpClient;
}
@@ -69,22 +69,24 @@ public class ReactorClientHttpConnector implements ClientHttpConnector {
}
return this.httpClient
.request(adaptHttpMethod(method),
uri.toString(),
request -> requestCallback.apply(adaptRequest(method, uri, request)))
.map(this::adaptResponse);
.request(adaptHttpMethod(method))
.uri(uri.toString())
.send((req, out) -> requestCallback.apply(adaptRequest(method, uri, req, out)))
.responseConnection((res, con) -> Mono.just(adaptResponse(res, con.inbound(), con.outbound().alloc())))
.next();
}
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 ReactorClientHttpRequest adaptRequest(HttpMethod method, URI uri, HttpClientRequest request, NettyOutbound out) {
return new ReactorClientHttpRequest(method, uri, request, out);
}
private ClientHttpResponse adaptResponse(HttpClientResponse response) {
return new ReactorClientHttpResponse(response);
private ClientHttpResponse adaptResponse(HttpClientResponse response, NettyInbound nettyInbound,
ByteBufAllocator alloc) {
return new ReactorClientHttpResponse(response, nettyInbound, alloc);
}
}

View File

@@ -25,7 +25,8 @@ import io.netty.handler.codec.http.cookie.DefaultCookie;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.http.client.HttpClientRequest;
import reactor.netty.NettyOutbound;
import reactor.netty.http.client.HttpClientRequest;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
@@ -38,7 +39,7 @@ import org.springframework.http.ZeroCopyHttpOutputMessage;
*
* @author Brian Clozel
* @since 5.0
* @see reactor.ipc.netty.http.client.HttpClient
* @see reactor.netty.http.client.HttpClient
*/
class ReactorClientHttpRequest extends AbstractClientHttpRequest implements ZeroCopyHttpOutputMessage {
@@ -48,15 +49,18 @@ class ReactorClientHttpRequest extends AbstractClientHttpRequest implements Zero
private final HttpClientRequest httpRequest;
private final NettyOutbound out;
private final NettyDataBufferFactory bufferFactory;
public ReactorClientHttpRequest(HttpMethod httpMethod, URI uri,
HttpClientRequest httpRequest) {
HttpClientRequest httpRequest, NettyOutbound out) {
this.httpMethod = httpMethod;
this.uri = uri;
this.httpRequest = httpRequest.failOnClientError(false).failOnServerError(false);
this.bufferFactory = new NettyDataBufferFactory(httpRequest.alloc());
this.httpRequest = httpRequest;
this.out = out;
this.bufferFactory = new NettyDataBufferFactory(out.alloc());
}
@@ -77,14 +81,14 @@ class ReactorClientHttpRequest extends AbstractClientHttpRequest implements Zero
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
return doCommit(() -> this.httpRequest
return doCommit(() -> this.out
.send(Flux.from(body).map(NettyDataBufferFactory::toByteBuf)).then());
}
@Override
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
Publisher<Publisher<ByteBuf>> byteBufs = Flux.from(body).map(ReactorClientHttpRequest::toByteBufs);
return doCommit(() -> this.httpRequest.sendGroups(byteBufs).then());
return doCommit(() -> this.out.sendGroups(byteBufs).then());
}
private static Publisher<ByteBuf> toByteBufs(Publisher<? extends DataBuffer> dataBuffers) {
@@ -93,12 +97,12 @@ class ReactorClientHttpRequest extends AbstractClientHttpRequest implements Zero
@Override
public Mono<Void> writeWith(File file, long position, long count) {
return doCommit(() -> this.httpRequest.sendFile(file.toPath(), position, count).then());
return doCommit(() -> this.out.sendFile(file.toPath(), position, count).then());
}
@Override
public Mono<Void> setComplete() {
return doCommit(() -> httpRequest.sendHeaders().then());
return doCommit(() -> out.then());
}
@Override

View File

@@ -19,7 +19,8 @@ package org.springframework.http.client.reactive;
import java.util.Collection;
import reactor.core.publisher.Flux;
import reactor.ipc.netty.http.client.HttpClientResponse;
import reactor.netty.NettyInbound;
import reactor.netty.http.client.HttpClientResponse;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
@@ -30,12 +31,14 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import io.netty.buffer.ByteBufAllocator;
/**
* {@link ClientHttpResponse} implementation for the Reactor-Netty HTTP client.
*
* @author Brian Clozel
* @since 5.0
* @see reactor.ipc.netty.http.client.HttpClient
* @see reactor.netty.http.client.HttpClient
*/
class ReactorClientHttpResponse implements ClientHttpResponse {
@@ -43,16 +46,21 @@ class ReactorClientHttpResponse implements ClientHttpResponse {
private final HttpClientResponse response;
private final NettyInbound nettyInbound;
public ReactorClientHttpResponse(HttpClientResponse response) {
public ReactorClientHttpResponse(HttpClientResponse response, NettyInbound nettyInbound,
ByteBufAllocator alloc) {
this.response = response;
this.dataBufferFactory = new NettyDataBufferFactory(response.channel().alloc());
this.nettyInbound = nettyInbound;
this.dataBufferFactory = new NettyDataBufferFactory(alloc);
}
@Override
public Flux<DataBuffer> getBody() {
return response.receive()
return nettyInbound
.receive()
.map(buf -> {
buf.retain();
return dataBufferFactory.wrap(buf);

View File

@@ -23,8 +23,8 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.http.server.HttpServerRequest;
import reactor.ipc.netty.http.server.HttpServerResponse;
import reactor.netty.http.server.HttpServerRequest;
import reactor.netty.http.server.HttpServerResponse;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpMethod;

View File

@@ -21,12 +21,12 @@ import java.net.URI;
import java.net.URISyntaxException;
import javax.net.ssl.SSLSession;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.ssl.SslHandler;
import reactor.core.publisher.Flux;
import reactor.ipc.netty.http.server.HttpServerRequest;
import reactor.netty.Connection;
import reactor.netty.http.server.HttpServerRequest;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
@@ -90,16 +90,14 @@ class ReactorServerHttpRequest extends AbstractServerHttpRequest {
}
}
else {
InetSocketAddress localAddress = (InetSocketAddress) request.context().channel().localAddress();
InetSocketAddress localAddress = request.hostAddress();
return new URI(scheme, null, localAddress.getHostString(),
localAddress.getPort(), null, null, null);
}
}
private static String getScheme(HttpServerRequest request) {
ChannelPipeline pipeline = request.context().channel().pipeline();
boolean ssl = pipeline.get(SslHandler.class) != null;
return ssl ? "https" : "http";
return request.scheme();
}
private static String resolveRequestUri(HttpServerRequest request) {
@@ -157,7 +155,7 @@ class ReactorServerHttpRequest extends AbstractServerHttpRequest {
@Nullable
protected SslInfo initSslInfo() {
SslHandler sslHandler = this.request.context().channel().pipeline().get(SslHandler.class);
SslHandler sslHandler = ((Connection) this.request).channel().pipeline().get(SslHandler.class);
if (sslHandler != null) {
SSLSession session = sslHandler.engine().getSession();
return new DefaultSslInfo(session);

View File

@@ -25,7 +25,7 @@ import io.netty.handler.codec.http.cookie.DefaultCookie;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.http.server.HttpServerResponse;
import reactor.netty.http.server.HttpServerResponse;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;