Skip to content

Commit 6fea585

Browse files
committed
Write ResponseStatusException headers in WebFlux error responses
See gh-18831 Signed-off-by: USJUN <u.s.junn@gmail.com>
1 parent c731cfd commit 6fea585

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

module/spring-boot-webflux/src/main/java/org/springframework/boot/webflux/autoconfigure/error/AbstractErrorWebExceptionHandler.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.springframework.web.reactive.function.server.ServerRequest;
4646
import org.springframework.web.reactive.function.server.ServerResponse;
4747
import org.springframework.web.reactive.result.view.ViewResolver;
48+
import org.springframework.web.server.ResponseStatusException;
4849
import org.springframework.web.server.ServerWebExchange;
4950
import org.springframework.web.util.DisconnectedClientHelper;
5051
import org.springframework.web.util.HtmlUtils;
@@ -55,6 +56,7 @@
5556
* @author Brian Clozel
5657
* @author Scott Frederick
5758
* @author Moritz Halbritter
59+
* @author US JUN
5860
* @since 4.0.0
5961
* @see ErrorAttributes
6062
*/
@@ -296,7 +298,7 @@ public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
296298
.switchIfEmpty(Mono.error(throwable))
297299
.flatMap((handler) -> handler.handle(request))
298300
.doOnNext((response) -> logError(request, response, throwable))
299-
.flatMap((response) -> write(exchange, response));
301+
.flatMap((response) -> write(exchange, response, throwable));
300302
}
301303

302304
private boolean isDisconnectedClientError(Throwable ex) {
@@ -333,7 +335,12 @@ private String formatRequest(ServerRequest request) {
333335
return "HTTP " + request.method() + " \"" + request.path() + query + "\"";
334336
}
335337

336-
private Mono<? extends Void> write(ServerWebExchange exchange, ServerResponse response) {
338+
private Mono<? extends Void> write(ServerWebExchange exchange, ServerResponse response, Throwable throwable) {
339+
if (throwable instanceof ResponseStatusException responseStatusException) {
340+
responseStatusException.getHeaders()
341+
.forEach((name, values) -> values
342+
.forEach((value) -> exchange.getResponse().getHeaders().add(name, value)));
343+
}
337344
// force content-type since writeTo won't overwrite response header values
338345
exchange.getResponse().getHeaders().setContentType(response.headers().getContentType());
339346
return response.writeTo(exchange, new ResponseContext());

module/spring-boot-webflux/src/test/java/org/springframework/boot/webflux/autoconfigure/error/DefaultErrorWebExceptionHandlerIntegrationTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import org.springframework.context.annotation.Bean;
5151
import org.springframework.context.annotation.Configuration;
5252
import org.springframework.core.annotation.Order;
53+
import org.springframework.http.HttpHeaders;
54+
import org.springframework.http.HttpMethod;
5355
import org.springframework.http.HttpStatus;
5456
import org.springframework.http.MediaType;
5557
import org.springframework.http.codec.ServerCodecConfigurer;
@@ -75,6 +77,7 @@
7577
*
7678
* @author Brian Clozel
7779
* @author Scott Frederick
80+
* @author US JUN
7881
*/
7982
@ExtendWith(OutputCaptureExtension.class)
8083
class DefaultErrorWebExceptionHandlerIntegrationTests {
@@ -381,6 +384,20 @@ void statusException() {
381384
});
382385
}
383386

387+
@Test // gh-18831
388+
void responseStatusExceptionHeaders() {
389+
this.contextRunner.run((context) -> {
390+
WebTestClient client = getWebClient(context);
391+
client.post()
392+
.uri("/badRequest")
393+
.exchange()
394+
.expectStatus()
395+
.isEqualTo(HttpStatus.METHOD_NOT_ALLOWED)
396+
.expectHeader()
397+
.valueEquals(HttpHeaders.ALLOW, HttpMethod.GET.name());
398+
});
399+
}
400+
384401
@Test
385402
void defaultErrorView() {
386403
this.contextRunner

0 commit comments

Comments
 (0)