From 2ed81be83103d27e4a38a12711fc1e96f6519522 Mon Sep 17 00:00:00 2001 From: Ilya Lukyanovich Date: Mon, 3 Jun 2019 15:02:44 +0300 Subject: [PATCH] Fix MockHttpServletRequest.setCookies to produce single cookie header Prior to this commit, MockHttpServletRequest.setCookies() produced one Cookie header per supplied cookie, resulting in multiple Cookie headers which violates the specification. This commit fixes this by ensuring that all cookie name-value pairs are stored under a single Cookie header, separated by a semicolon. Closes gh-23074 --- .../mock/web/MockHttpServletRequest.java | 18 +++++++++++++----- .../mock/web/MockHttpServletRequestTests.java | 4 +++- .../mock/web/test/MockHttpServletRequest.java | 19 ++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index 94e3a8f6cf..09d9ae77dd 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -41,6 +41,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.stream.Collectors; import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; @@ -58,6 +59,7 @@ import javax.servlet.http.Part; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.LinkedCaseInsensitiveMap; @@ -973,12 +975,18 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCookies(@Nullable Cookie... cookies) { this.cookies = (ObjectUtils.isEmpty(cookies) ? null : cookies); - this.headers.remove(HttpHeaders.COOKIE); - if (this.cookies != null) { - Arrays.stream(this.cookies) - .map(c -> c.getName() + '=' + (c.getValue() == null ? "" : c.getValue())) - .forEach(value -> doAddHeaderValue(HttpHeaders.COOKIE, value, false)); + if (this.cookies == null) { + removeHeader(HttpHeaders.COOKIE); } + else { + doAddHeaderValue(HttpHeaders.COOKIE, encodeCookies(this.cookies), true); + } + } + + private static String encodeCookies(@NonNull Cookie... cookies) { + return Arrays.stream(cookies) + .map(c -> c.getName() + '=' + (c.getValue() == null ? "" : c.getValue())) + .collect(Collectors.joining("; ")); } @Override diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index c28b95b378..7ad4d6bd2f 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -292,7 +292,9 @@ public class MockHttpServletRequestTests { assertEquals("bar", cookies[0].getValue()); assertEquals("baz", cookies[1].getName()); assertEquals("qux", cookies[1].getValue()); - assertEquals(Arrays.asList("foo=bar", "baz=qux"), cookieHeaders); + + assertEquals(1, cookieHeaders.size()); + assertEquals("foo=bar; baz=qux", cookieHeaders.get(0)); } @Test diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java index fbfa8721f0..f2fb831b5c 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java @@ -41,6 +41,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.stream.Collectors; import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; @@ -58,6 +59,7 @@ import javax.servlet.http.Part; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.LinkedCaseInsensitiveMap; @@ -973,14 +975,20 @@ public class MockHttpServletRequest implements HttpServletRequest { public void setCookies(@Nullable Cookie... cookies) { this.cookies = (ObjectUtils.isEmpty(cookies) ? null : cookies); - this.headers.remove(HttpHeaders.COOKIE); - if (this.cookies != null) { - Arrays.stream(this.cookies) - .map(c -> c.getName() + '=' + (c.getValue() == null ? "" : c.getValue())) - .forEach(value -> doAddHeaderValue(HttpHeaders.COOKIE, value, false)); + if (this.cookies == null) { + removeHeader(HttpHeaders.COOKIE); + } + else { + doAddHeaderValue(HttpHeaders.COOKIE, encodeCookies(this.cookies), true); } } + private static String encodeCookies(@NonNull Cookie... cookies) { + return Arrays.stream(cookies) + .map(c -> c.getName() + '=' + (c.getValue() == null ? "" : c.getValue())) + .collect(Collectors.joining("; ")); + } + @Override @Nullable public Cookie[] getCookies() { @@ -1297,6 +1305,7 @@ public class MockHttpServletRequest implements HttpServletRequest { * Otherwise it simply returns the current session id. * @since 4.0.3 */ + @Override public String changeSessionId() { Assert.isTrue(this.session != null, "The request does not have a session"); if (this.session instanceof MockHttpSession) {