Skip to content

Commit c84adc9

Browse files
committed
Merge branch '5.0.x'
2 parents 661fcb2 + 323338a commit c84adc9

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

spring-cloud-gateway-server-webflux/src/main/java/org/springframework/cloud/gateway/filter/NettyWriteResponseFilter.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
/**
4747
* @author Spencer Gibb
48+
* @author Seungbin Ko
4849
*/
4950
public class NettyWriteResponseFilter implements GlobalFilter, Ordered {
5051

@@ -92,12 +93,21 @@ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
9293
if (connection == null) {
9394
return Mono.empty();
9495
}
96+
ServerHttpResponse response = exchange.getResponse();
97+
if (response.isCommitted()) {
98+
if (log.isDebugEnabled()) {
99+
log.debug("NettyWriteResponseFilter response already committed, discarding inbound: "
100+
+ connection.channel().id().asShortText() + ", outbound: "
101+
+ exchange.getLogPrefix());
102+
}
103+
cleanup(exchange);
104+
return Mono.empty();
105+
}
95106
if (log.isTraceEnabled()) {
96107
log.trace("NettyWriteResponseFilter start inbound: "
97108
+ connection.channel().id().asShortText() + ", outbound: "
98109
+ exchange.getLogPrefix());
99110
}
100-
ServerHttpResponse response = exchange.getResponse();
101111

102112
// TODO: needed?
103113
final Flux<DataBuffer> body = connection

spring-cloud-gateway-server-webflux/src/test/java/org/springframework/cloud/gateway/filter/NettyWriteResponseFilterTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,26 @@
2121

2222
import io.netty.buffer.ByteBuf;
2323
import org.junit.jupiter.api.Test;
24+
import reactor.core.publisher.Mono;
25+
import reactor.netty.Connection;
2426

2527
import org.springframework.core.io.buffer.DataBuffer;
2628
import org.springframework.core.io.buffer.NettyDataBufferFactory;
2729
import org.springframework.core.io.buffer.PooledDataBuffer;
30+
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
2831
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
32+
import org.springframework.mock.web.server.MockServerWebExchange;
2933

3034
import static io.netty.buffer.PooledByteBufAllocator.DEFAULT;
3135
import static org.assertj.core.api.Assertions.assertThat;
36+
import static org.mockito.Mockito.mock;
37+
import static org.mockito.Mockito.never;
38+
import static org.mockito.Mockito.verify;
39+
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_CONN_ATTR;
3240

3341
/**
3442
* @author Violeta Georgieva
43+
* @author Seungbin Ko
3544
*/
3645
public class NettyWriteResponseFilterTests {
3746

@@ -45,6 +54,20 @@ public void testWrap_DefaultDataBufferFactory() {
4554
doTestWrap(new MockServerHttpResponse());
4655
}
4756

57+
@Test
58+
public void committedResponseDisposesConnectionWithoutWriting() {
59+
NettyWriteResponseFilter filter = new NettyWriteResponseFilter(new ArrayList<>(), null);
60+
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/").build());
61+
exchange.getResponse().setComplete().block();
62+
Connection connection = mock(Connection.class);
63+
exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);
64+
65+
filter.filter(exchange, ex -> Mono.empty()).block();
66+
67+
verify(connection).dispose();
68+
verify(connection, never()).inbound();
69+
}
70+
4871
private void doTestWrap(MockServerHttpResponse response) {
4972
NettyWriteResponseFilter filter = new NettyWriteResponseFilter(new ArrayList<>(), null);
5073

0 commit comments

Comments
 (0)