Fixes issues with netty assumptions

Fixes issues with concrete interface realization assumptions in ServerWebExchangeUtils (DataBuffer -> NettyDataBuffer and DataBufferFactory -> NettyDataBufferFactory)

Fixes gh-2193
This commit is contained in:
Melnichuk Stas
2021-03-29 19:59:11 +03:00
committed by spencergibb
parent c414f58c7b
commit 68dcc35511
2 changed files with 32 additions and 7 deletions

View File

@@ -25,7 +25,7 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import io.netty.buffer.EmptyByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux;
@@ -36,9 +36,10 @@ import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory;
import org.springframework.cloud.gateway.handler.AsyncPredicate;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.NettyDataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -343,10 +344,9 @@ public final class ServerWebExchangeUtils {
private static <T> Mono<T> cacheRequestBody(ServerWebExchange exchange, boolean cacheDecoratedRequest,
Function<ServerHttpRequest, Mono<T>> function) {
ServerHttpResponse response = exchange.getResponse();
NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();
DataBufferFactory factory = response.bufferFactory();
// Join all the DataBuffers so we have a single DataBuffer for the body
return DataBufferUtils.join(exchange.getRequest().getBody())
.defaultIfEmpty(factory.wrap(new EmptyByteBuf(factory.getByteBufAllocator())))
return DataBufferUtils.join(exchange.getRequest().getBody()).defaultIfEmpty(factory.wrap(new byte[] {}))
.map(dataBuffer -> decorate(exchange, dataBuffer, cacheDecoratedRequest))
.switchIfEmpty(Mono.just(exchange.getRequest())).flatMap(function);
}
@@ -369,8 +369,18 @@ public final class ServerWebExchangeUtils {
return null;
}
// TODO: deal with Netty
NettyDataBuffer pdb = (NettyDataBuffer) dataBuffer;
return pdb.factory().wrap(pdb.getNativeBuffer().retainedSlice());
if (dataBuffer instanceof NettyDataBuffer) {
NettyDataBuffer pdb = (NettyDataBuffer) dataBuffer;
return pdb.factory().wrap(pdb.getNativeBuffer().retainedSlice());
}
else if (dataBuffer instanceof DefaultDataBuffer) {
DefaultDataBuffer ddf = (DefaultDataBuffer) dataBuffer;
return ddf.factory().wrap(Unpooled.wrappedBuffer(ddf.getNativeBuffer()).nioBuffer());
}
else {
throw new IllegalArgumentException(
"Unable to handle DataBuffer of type " + dataBuffer.getClass());
}
}).flux();
}
};

View File

@@ -23,10 +23,14 @@ import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.expand;
public class ServerWebExchangeUtilsTests {
@@ -52,6 +56,17 @@ public class ServerWebExchangeUtilsTests {
Assert.assertThrows(IllegalArgumentException.class, () -> expand(exchange, "my-{foo}-{baz}"));
}
@Test
public void defaultDataBufferHandling() {
MockServerWebExchange exchange = mockExchange(Collections.emptyMap());
exchange.getAttributes().put(CACHED_REQUEST_BODY_ATTR, "foo");
ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange,
(serverHttpRequest) -> ServerRequest
.create(exchange.mutate().request(serverHttpRequest).build(), HandlerStrategies.withDefaults().messageReaders())
.bodyToMono(DefaultDataBuffer.class)).block();
}
private MockServerWebExchange mockExchange(Map<String, String> vars) {
MockServerHttpRequest request = MockServerHttpRequest.get("/get").build();
MockServerWebExchange exchange = MockServerWebExchange.from(request);