Skip to content

Commit a8331ba

Browse files
committed
CompositeServerHttpHeadersWriter Executes Sequentially
Fixes gh-7731
1 parent 31b999e commit a8331ba

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

web/src/main/java/org/springframework/security/web/server/header/CompositeServerHttpHeadersWriter.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
*/
1616
package org.springframework.security.web.server.header;
1717

18-
import java.util.Arrays;
19-
import java.util.List;
20-
import java.util.ArrayList;
21-
2218
import org.springframework.web.server.ServerWebExchange;
23-
19+
import reactor.core.publisher.Flux;
2420
import reactor.core.publisher.Mono;
2521

22+
import java.util.Arrays;
23+
import java.util.List;
24+
2625
/**
2726
* Combines multiple {@link ServerHttpHeadersWriter} instances into a single instance.
2827
*
@@ -42,10 +41,8 @@ public CompositeServerHttpHeadersWriter(List<ServerHttpHeadersWriter> writers) {
4241

4342
@Override
4443
public Mono<Void> writeHttpHeaders(ServerWebExchange exchange) {
45-
List<Mono<Void>> results = new ArrayList<>();
46-
for (ServerHttpHeadersWriter writer : writers) {
47-
results.add(writer.writeHttpHeaders(exchange));
48-
}
49-
return Mono.when(results);
44+
return Flux.fromIterable(this.writers)
45+
.concatMap(w -> w.writeHttpHeaders(exchange))
46+
.then();
5047
}
5148
}

web/src/test/java/org/springframework/security/web/server/header/CompositeServerHttpHeadersWriterTests.java

+32-10
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@
1515
*/
1616
package org.springframework.security.web.server.header;
1717

18-
import static org.mockito.Mockito.verify;
19-
import static org.mockito.Mockito.when;
20-
21-
import java.util.Arrays;
22-
2318
import org.junit.Before;
2419
import org.junit.Test;
2520
import org.junit.runner.RunWith;
@@ -28,10 +23,19 @@
2823
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
2924
import org.springframework.mock.web.server.MockServerWebExchange;
3025
import org.springframework.web.server.ServerWebExchange;
31-
3226
import reactor.core.publisher.Mono;
3327
import reactor.test.StepVerifier;
3428

29+
import java.time.Duration;
30+
import java.util.Arrays;
31+
import java.util.concurrent.CountDownLatch;
32+
import java.util.concurrent.TimeUnit;
33+
import java.util.concurrent.atomic.AtomicBoolean;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
import static org.mockito.Mockito.verify;
37+
import static org.mockito.Mockito.when;
38+
3539
/**
3640
*
3741
* @author Rob Winch
@@ -55,7 +59,6 @@ public void setup() {
5559
@Test
5660
public void writeHttpHeadersWhenErrorNoErrorThenError() {
5761
when(writer1.writeHttpHeaders(exchange)).thenReturn(Mono.error(new RuntimeException()));
58-
when(writer2.writeHttpHeaders(exchange)).thenReturn(Mono.empty());
5962

6063
Mono<Void> result = writer.writeHttpHeaders(exchange);
6164

@@ -64,13 +67,11 @@ public void writeHttpHeadersWhenErrorNoErrorThenError() {
6467
.verify();
6568

6669
verify(writer1).writeHttpHeaders(exchange);
67-
verify(writer2).writeHttpHeaders(exchange);
6870
}
6971

7072
@Test
7173
public void writeHttpHeadersWhenErrorErrorThenError() {
7274
when(writer1.writeHttpHeaders(exchange)).thenReturn(Mono.error(new RuntimeException()));
73-
when(writer2.writeHttpHeaders(exchange)).thenReturn(Mono.error(new RuntimeException()));
7475

7576
Mono<Void> result = writer.writeHttpHeaders(exchange);
7677

@@ -79,7 +80,6 @@ public void writeHttpHeadersWhenErrorErrorThenError() {
7980
.verify();
8081

8182
verify(writer1).writeHttpHeaders(exchange);
82-
verify(writer2).writeHttpHeaders(exchange);
8383
}
8484

8585
@Test
@@ -96,4 +96,26 @@ public void writeHttpHeadersWhenNoErrorThenNoError() {
9696
verify(writer1).writeHttpHeaders(exchange);
9797
verify(writer2).writeHttpHeaders(exchange);
9898
}
99+
100+
@Test
101+
public void writeHttpHeadersSequential() throws Exception {
102+
AtomicBoolean slowDone = new AtomicBoolean();
103+
CountDownLatch latch = new CountDownLatch(1);
104+
ServerHttpHeadersWriter slow = exchange ->
105+
Mono.delay(Duration.ofMillis(100))
106+
.doOnSuccess(__ -> slowDone.set(true))
107+
.then();
108+
ServerHttpHeadersWriter second = exchange ->
109+
Mono.fromRunnable(() -> {
110+
latch.countDown();
111+
assertThat(slowDone.get())
112+
.describedAs("ServerLogoutHandler should be executed sequentially")
113+
.isTrue();
114+
});
115+
CompositeServerHttpHeadersWriter writer = new CompositeServerHttpHeadersWriter(slow, second);
116+
117+
writer.writeHttpHeaders(this.exchange).block();
118+
119+
assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
120+
}
99121
}

0 commit comments

Comments
 (0)