Skip to content

Commit e2fa282

Browse files
committed
Merge pull request #1055 from rwinch/SPR-14265
2 parents 92f1b69 + d10134b commit e2fa282

File tree

3 files changed

+98
-25
lines changed

3 files changed

+98
-25
lines changed

spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
1717
package org.springframework.test.web.servlet.htmlunit;
1818

1919
import java.io.IOException;
20+
import java.util.Date;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223

24+
import com.gargoylesoftware.htmlunit.CookieManager;
2325
import com.gargoylesoftware.htmlunit.WebClient;
2426
import com.gargoylesoftware.htmlunit.WebConnection;
2527
import com.gargoylesoftware.htmlunit.WebRequest;
2628
import com.gargoylesoftware.htmlunit.WebResponse;
29+
import com.gargoylesoftware.htmlunit.util.Cookie;
2730

2831
import org.springframework.mock.web.MockHttpServletResponse;
2932
import org.springframework.mock.web.MockHttpSession;
@@ -62,6 +65,7 @@ public final class MockMvcWebConnection implements WebConnection {
6265

6366
private WebClient webClient;
6467

68+
6569
/**
6670
* Create a new instance that assumes the context path of the application
6771
* is {@code ""} (i.e., the root context).
@@ -124,6 +128,27 @@ public MockMvcWebConnection(MockMvc mockMvc, String contextPath) {
124128
this(mockMvc, new WebClient(), contextPath);
125129
}
126130

131+
/**
132+
* Validate the supplied {@code contextPath}.
133+
* <p>If the value is not {@code null}, it must conform to
134+
* {@link javax.servlet.http.HttpServletRequest#getContextPath()} which
135+
* states that it can be an empty string and otherwise must start with
136+
* a "/" character and not end with a "/" character.
137+
* @param contextPath the path to validate
138+
*/
139+
static void validateContextPath(String contextPath) {
140+
if (contextPath == null || "".equals(contextPath)) {
141+
return;
142+
}
143+
if (!contextPath.startsWith("/")) {
144+
throw new IllegalArgumentException("contextPath '" + contextPath + "' must start with '/'.");
145+
}
146+
if (contextPath.endsWith("/")) {
147+
throw new IllegalArgumentException("contextPath '" + contextPath + "' must not end with '/'.");
148+
}
149+
}
150+
151+
127152
public void setWebClient(WebClient webClient) {
128153
Assert.notNull(webClient, "WebClient must not be null");
129154
this.webClient = webClient;
@@ -142,6 +167,7 @@ public WebResponse getResponse(WebRequest webRequest) throws IOException {
142167
httpServletResponse = getResponse(requestBuilder);
143168
forwardedUrl = httpServletResponse.getForwardedUrl();
144169
}
170+
storeCookies(webRequest, httpServletResponse.getCookies());
145171

146172
return new MockWebResponseBuilder(startTime, webRequest, httpServletResponse).build();
147173
}
@@ -158,29 +184,29 @@ private MockHttpServletResponse getResponse(RequestBuilder requestBuilder) throw
158184
return resultActions.andReturn().getResponse();
159185
}
160186

161-
@Override
162-
public void close() {
163-
}
164-
165-
166-
/**
167-
* Validate the supplied {@code contextPath}.
168-
* <p>If the value is not {@code null}, it must conform to
169-
* {@link javax.servlet.http.HttpServletRequest#getContextPath()} which
170-
* states that it can be an empty string and otherwise must start with
171-
* a "/" character and not end with a "/" character.
172-
* @param contextPath the path to validate
173-
*/
174-
static void validateContextPath(String contextPath) {
175-
if (contextPath == null || "".equals(contextPath)) {
187+
private void storeCookies(WebRequest webRequest, javax.servlet.http.Cookie[] cookies) {
188+
if (cookies == null) {
176189
return;
177190
}
178-
if (!contextPath.startsWith("/")) {
179-
throw new IllegalArgumentException("contextPath '" + contextPath + "' must start with '/'.");
180-
}
181-
if (contextPath.endsWith("/")) {
182-
throw new IllegalArgumentException("contextPath '" + contextPath + "' must not end with '/'.");
191+
Date now = new Date();
192+
CookieManager cookieManager = this.webClient.getCookieManager();
193+
for (javax.servlet.http.Cookie cookie : cookies) {
194+
if (cookie.getDomain() == null) {
195+
cookie.setDomain(webRequest.getUrl().getHost());
196+
}
197+
Cookie toManage = MockWebResponseBuilder.createCookie(cookie);
198+
Date expires = toManage.getExpires();
199+
if (expires == null || expires.after(now)) {
200+
cookieManager.addCookie(toManage);
201+
}
202+
else {
203+
cookieManager.removeCookie(toManage);
204+
}
183205
}
184206
}
185207

208+
@Override
209+
public void close() {
210+
}
211+
186212
}

spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilder.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ private List<NameValuePair> responseHeaders() {
112112
}
113113

114114
private String valueOfCookie(Cookie cookie) {
115+
return createCookie(cookie).toString();
116+
}
117+
118+
static com.gargoylesoftware.htmlunit.util.Cookie createCookie(Cookie cookie) {
115119
Date expires = null;
116120
if (cookie.getMaxAge() > -1) {
117121
expires = new Date(System.currentTimeMillis() + cookie.getMaxAge() * 1000);
@@ -125,7 +129,6 @@ private String valueOfCookie(Cookie cookie) {
125129
if(cookie.isHttpOnly()) {
126130
result.setAttribute("httponly", "true");
127131
}
128-
return new com.gargoylesoftware.htmlunit.util.Cookie(result).toString();
132+
return new com.gargoylesoftware.htmlunit.util.Cookie(result);
129133
}
130-
131134
}

spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import java.io.IOException;
2020
import java.net.URL;
2121
import javax.servlet.http.HttpServletRequest;
22+
import javax.servlet.http.HttpServletResponse;
2223

24+
import com.gargoylesoftware.htmlunit.HttpMethod;
2325
import com.gargoylesoftware.htmlunit.WebClient;
2426
import com.gargoylesoftware.htmlunit.WebRequest;
2527
import com.gargoylesoftware.htmlunit.WebResponse;
@@ -38,7 +40,10 @@
3840
import org.springframework.tests.Assume;
3941
import org.springframework.tests.TestGroup;
4042
import org.springframework.web.bind.annotation.CookieValue;
43+
import org.springframework.web.bind.annotation.DeleteMapping;
44+
import org.springframework.web.bind.annotation.PostMapping;
4145
import org.springframework.web.bind.annotation.RequestMapping;
46+
import org.springframework.web.bind.annotation.RequestParam;
4247
import org.springframework.web.bind.annotation.RestController;
4348
import org.springframework.web.context.WebApplicationContext;
4449
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@@ -103,11 +108,22 @@ public void cookieManagerShared() throws Exception {
103108
this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build();
104109
WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build();
105110

106-
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo(""));
111+
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
107112
client.getCookieManager().addCookie(new Cookie("localhost", "cookie", "cookieManagerShared"));
108113
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("cookieManagerShared"));
109114
}
110115

116+
@Test // SPR-14265
117+
public void cookiesAreManaged() throws Exception {
118+
this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build();
119+
WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build();
120+
121+
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
122+
assertThat(postResponse(client, "http://localhost/?cookie=foo").getContentAsString(), equalTo("Set"));
123+
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("foo"));
124+
assertThat(deleteResponse(client, "http://localhost/").getContentAsString(), equalTo("Delete"));
125+
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
126+
}
111127

112128
private void assertMockMvcUsed(WebClient client, String url) throws Exception {
113129
assertThat(getResponse(client, url).getContentAsString(), equalTo("mvc"));
@@ -118,7 +134,19 @@ private void assertMockMvcNotUsed(WebClient client, String url) throws Exception
118134
}
119135

120136
private WebResponse getResponse(WebClient client, String url) throws IOException {
121-
return client.getWebConnection().getResponse(new WebRequest(new URL(url)));
137+
return createResponse(client, new WebRequest(new URL(url)));
138+
}
139+
140+
private WebResponse postResponse(WebClient client, String url) throws IOException {
141+
return createResponse(client, new WebRequest(new URL(url), HttpMethod.POST));
142+
}
143+
144+
private WebResponse deleteResponse(WebClient client, String url) throws IOException {
145+
return createResponse(client, new WebRequest(new URL(url), HttpMethod.DELETE));
146+
}
147+
148+
private WebResponse createResponse(WebClient client, WebRequest request) throws IOException {
149+
return client.getWebConnection().getResponse(request);
122150
}
123151

124152

@@ -139,10 +167,26 @@ public String contextPath(HttpServletRequest request) {
139167
@RestController
140168
static class CookieController {
141169

170+
static final String COOKIE_NAME = "cookie";
171+
142172
@RequestMapping(path = "/", produces = "text/plain")
143-
String cookie(@CookieValue("cookie") String cookie) {
173+
String cookie(@CookieValue(name = COOKIE_NAME, defaultValue = "NA") String cookie) {
144174
return cookie;
145175
}
176+
177+
@PostMapping(path = "/", produces = "text/plain")
178+
String setCookie(@RequestParam String cookie, HttpServletResponse response) {
179+
response.addCookie(new javax.servlet.http.Cookie(COOKIE_NAME, cookie));
180+
return "Set";
181+
}
182+
183+
@DeleteMapping(path = "/", produces = "text/plain")
184+
String deleteCookie(HttpServletResponse response) {
185+
javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(COOKIE_NAME, "");
186+
cookie.setMaxAge(0);
187+
response.addCookie(cookie);
188+
return "Delete";
189+
}
146190
}
147191

148192
}

0 commit comments

Comments
 (0)