Skip to content

Commit dca3dd2

Browse files
fix(webflux): preserve multi-buffer response bodies
1 parent c1ab014 commit dca3dd2

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

‎spring-boot-starter/spring-boot-starter-webflux/src/main/java/com/getyourguide/openapi/validation/filter/decorator/BodyCachingServerHttpResponseDecorator.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import lombok.Setter;
99
import org.reactivestreams.Publisher;
1010
import org.springframework.core.io.buffer.DataBuffer;
11+
import org.springframework.core.io.buffer.DataBufferUtils;
1112
import org.springframework.http.server.reactive.ServerHttpResponse;
1213
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
1314
import org.springframework.lang.NonNull;
@@ -45,7 +46,7 @@ public Mono<Void> writeWith(@NonNull Publisher<? extends DataBuffer> body) {
4546
return super.writeWith(body);
4647
}
4748

48-
var buffer = Mono.from(body).doOnNext(dataBuffer -> {
49+
var buffer = DataBufferUtils.join(body).doOnNext(dataBuffer -> {
4950
cachedBody = dataBuffer.toString(StandardCharsets.UTF_8);
5051
if (onBodyCachedListener != null) {
5152
onBodyCachedListener.run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.getyourguide.openapi.validation.filter.decorator;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.mockito.ArgumentMatchers.any;
5+
import static org.mockito.ArgumentMatchers.eq;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.when;
8+
9+
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
10+
import com.getyourguide.openapi.validation.api.selector.TrafficSelector;
11+
import com.getyourguide.openapi.validation.factory.ReactiveMetaDataFactory;
12+
import java.nio.charset.StandardCharsets;
13+
import org.junit.jupiter.api.Test;
14+
import org.springframework.http.MediaType;
15+
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
16+
import reactor.core.publisher.Flux;
17+
18+
class BodyCachingServerHttpResponseDecoratorTest {
19+
20+
@Test
21+
public void whenResponseContainsMultipleBuffersThenAllBuffersAreWritten() {
22+
var delegate = new MockServerHttpResponse();
23+
delegate.getHeaders().setContentType(MediaType.APPLICATION_JSON);
24+
25+
var trafficSelector = mock(TrafficSelector.class);
26+
var requestMetaData = mock(RequestMetaData.class);
27+
when(trafficSelector.canResponseBeValidated(eq(requestMetaData), any())).thenReturn(true);
28+
29+
var decorator = new BodyCachingServerHttpResponseDecorator(
30+
delegate,
31+
trafficSelector,
32+
new ReactiveMetaDataFactory(),
33+
requestMetaData
34+
);
35+
36+
decorator.writeWith(Flux.just(
37+
delegate.bufferFactory().wrap("{\"name\":\"GetYour".getBytes(StandardCharsets.UTF_8)),
38+
delegate.bufferFactory().wrap("Guide\"}".getBytes(StandardCharsets.UTF_8))
39+
)).block();
40+
41+
assertEquals("{\"name\":\"GetYourGuide\"}", delegate.getBodyAsString().block());
42+
assertEquals("{\"name\":\"GetYourGuide\"}", decorator.getCachedBody());
43+
}
44+
}

0 commit comments

Comments
 (0)