From 298c9a6f1bda440dd8aacf2065ea58b85d062261 Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Wed, 31 Aug 2022 10:57:16 -0400 Subject: [PATCH 1/2] Redirect response wrapper should commit response This commit ensures that when using `sendRedirect`, the response wrapper behaves correctly with regards to the Servlet specification: 1. reset the response buffer to clear any partially written response 2. set the expected response HTTP headers 3. flush the buffer to commit the response Closes gh-29050 --- .../web/filter/RelativeRedirectResponseWrapper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java index d532c62513..0d418548c5 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java +++ b/spring-web/src/main/java/org/springframework/web/filter/RelativeRedirectResponseWrapper.java @@ -16,6 +16,8 @@ package org.springframework.web.filter; +import java.io.IOException; + import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @@ -44,9 +46,11 @@ final class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper { @Override - public void sendRedirect(String location) { + public void sendRedirect(String location) throws IOException { + resetBuffer(); setStatus(this.redirectStatus.value()); setHeader(HttpHeaders.LOCATION, location); + flushBuffer(); } From a42551202575dceb11b2eb31924faf0bb7f4bbdd Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Wed, 7 Sep 2022 14:58:50 +0200 Subject: [PATCH 2/2] Polish See gh-29050 --- .../web/filter/RelativeRedirectFilterTests.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/spring-web/src/test/java/org/springframework/web/filter/RelativeRedirectFilterTests.java b/spring-web/src/test/java/org/springframework/web/filter/RelativeRedirectFilterTests.java index dd23fd6ac2..73ce14fec3 100644 --- a/spring-web/src/test/java/org/springframework/web/filter/RelativeRedirectFilterTests.java +++ b/spring-web/src/test/java/org/springframework/web/filter/RelativeRedirectFilterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,41 +46,45 @@ public class RelativeRedirectFilterTests { @Test - public void sendRedirectHttpStatusWhenNullThenIllegalArgumentException() { + void sendRedirectHttpStatusWhenNullThenIllegalArgumentException() { assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRedirectStatus(null)); } @Test - public void sendRedirectHttpStatusWhenNot3xxThenIllegalArgumentException() { + void sendRedirectHttpStatusWhenNot3xxThenIllegalArgumentException() { assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRedirectStatus(HttpStatus.OK)); } @Test - public void doFilterSendRedirectWhenDefaultsThenLocationAnd303() throws Exception { + void doFilterSendRedirectWhenDefaultsThenLocationAnd303() throws Exception { String location = "/foo"; sendRedirect(location); InOrder inOrder = Mockito.inOrder(this.response); + inOrder.verify(this.response).resetBuffer(); inOrder.verify(this.response).setStatus(HttpStatus.SEE_OTHER.value()); inOrder.verify(this.response).setHeader(HttpHeaders.LOCATION, location); + inOrder.verify(this.response).flushBuffer(); } @Test - public void doFilterSendRedirectWhenCustomSendRedirectHttpStatusThenLocationAnd301() throws Exception { + void doFilterSendRedirectWhenCustomSendRedirectHttpStatusThenLocationAnd301() throws Exception { String location = "/foo"; HttpStatus status = HttpStatus.MOVED_PERMANENTLY; this.filter.setRedirectStatus(status); sendRedirect(location); InOrder inOrder = Mockito.inOrder(this.response); + inOrder.verify(this.response).resetBuffer(); inOrder.verify(this.response).setStatus(status.value()); inOrder.verify(this.response).setHeader(HttpHeaders.LOCATION, location); + inOrder.verify(this.response).flushBuffer(); } @Test - public void wrapOnceOnly() throws Exception { + void wrapOnceOnly() throws Exception { HttpServletResponse original = new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain();