Upgrade to Reactor Netty 0.8
Issue: SPR-16387
This commit is contained in:
committed by
Rossen Stoyanchev
parent
61ffbe5554
commit
ffbc75ae47
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user