From c3cde84e6b47b909955e92d2f15abcd8745a8fa2 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 11 Jan 2016 17:15:55 -0500 Subject: [PATCH] Polish cookie support HttpCookie is now immutable with factory methods to create a client cookie (name-value) vs a server cookie (name-value + attributes) including a builder for the latter. --- .../org/springframework/http/HttpCookie.java | 208 ++++++++++++++---- .../org/springframework/http/HttpHeaders.java | 23 +- .../reactive/AbstractServerHttpRequest.java | 35 +-- .../reactive/ReactorServerHttpRequest.java | 4 +- .../reactive/RxNettyServerHttpRequest.java | 21 +- .../reactive/RxNettyServerHttpResponse.java | 4 +- .../reactive/ServletServerHttpRequest.java | 21 +- .../reactive/ServletServerHttpResponse.java | 4 +- .../reactive/UndertowServerHttpRequest.java | 21 +- .../reactive/UndertowServerHttpResponse.java | 4 +- .../reactive/CookieIntegrationTests.java | 36 ++- 11 files changed, 251 insertions(+), 130 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/http/HttpCookie.java b/spring-web-reactive/src/main/java/org/springframework/http/HttpCookie.java index 18a140d236..5021b62614 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/HttpCookie.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/HttpCookie.java @@ -15,32 +15,52 @@ */ package org.springframework.http; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; + /** * Representation for an HTTP Cookie. * + *

Use the {@link #clientCookie} factory method to create a client-to-server, + * name-value pair cookie and the {@link #serverCookie} factory method to build + * a server-to-client cookie with additional attributes. + * * @author Rossen Stoyanchev * @see RFC 6265 */ -public class HttpCookie { +public final class HttpCookie { private final String name; private final String value; - private String domain; + private final int maxAge; - private String path; + private final String domain; - private long maxAge = Long.MIN_VALUE; + private final String path; - private boolean secure; + private final boolean secure; - private boolean httpOnly; + private final boolean httpOnly; - public HttpCookie(String name, String value) { + private HttpCookie(String name, String value) { + this(name, value, -1, null, null, false, false); + } + + private HttpCookie(String name, String value, int maxAge, String domain, String path, + boolean secure, boolean httpOnly) { + + Assert.hasLength(name, "'name' is required and must not be empty."); + Assert.hasLength(value, "'value' is required and must not be empty."); this.name = name; this.value = value; + this.maxAge = (maxAge > -1 ? maxAge : -1); + this.domain = domain; + this.path = path; + this.secure = secure; + this.httpOnly = httpOnly; } /** @@ -57,66 +77,180 @@ public class HttpCookie { return this.value; } - public HttpCookie setPath(String path) { - this.path = path; - return this; + /** + * Return the cookie "Max-Age" attribute in seconds. + * + *

A positive value indicates when the cookie expires relative to the + * current time. A value of 0 means the cookie should expire immediately. + * A negative value means no "Max-Age" attribute in which case the cookie + * is removed when the browser is closed. + */ + public int getMaxAge() { + return this.maxAge; } /** - * Return the domain attribute of the cookie. + * Return the cookie "Domain" attribute. */ public String getDomain() { return this.domain; } - public HttpCookie setDomain(String domain) { - this.domain = domain; - return this; - } - /** - * Return the path attribute of the cookie. + * Return the cookie "Path" attribute. */ public String getPath() { return this.path; } - public HttpCookie setMaxAge(long maxAge) { - this.maxAge = maxAge; - return this; + /** + * Return {@code true} if the cookie has the "Secure" attribute. + */ + public boolean isSecure() { + return this.secure; } /** - * Return the maximum age attribute of the cookie in seconds or - * {@link Long#MIN_VALUE} if not set. + * Return {@code true} if the cookie has the "HttpOnly" attribute. + * @see http://www.owasp.org/index.php/HTTPOnly */ - public long getMaxAge() { - return this.maxAge; + public boolean isHttpOnly() { + return this.httpOnly; } - public HttpCookie setSecure(boolean secure) { - this.secure = secure; - return this; + @Override + public int hashCode() { + int result = this.name.hashCode(); + result = 31 * result + ObjectUtils.nullSafeHashCode(this.domain); + result = 31 * result + ObjectUtils.nullSafeHashCode(this.path); + return result; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof HttpCookie)) { + return false; + } + HttpCookie otherCookie = (HttpCookie) other; + return (this.name.equalsIgnoreCase(otherCookie.getName()) && + ObjectUtils.nullSafeEquals(this.path, otherCookie.getPath()) && + ObjectUtils.nullSafeEquals(this.domain, otherCookie.getDomain())); } /** - * Return true if the "Secure" attribute of the cookie is present. + * Factory method to create a cookie sent from a client to a server. + * Client cookies are name-value pairs only without attributes. + * @param name the cookie name + * @param value the cookie value + * @return the created cookie instance */ - public boolean isSecure() { - return this.secure; + public static HttpCookie clientCookie(String name, String value) { + return new HttpCookie(name, value); } - public HttpCookie setHttpOnly(boolean httpOnly) { - this.httpOnly = httpOnly; - return this; + /** + * Factory method to obtain a builder for a server-defined cookie that starts + * with a name-value pair and may also include attributes. + * @param name the cookie name + * @param value the cookie value + * @return the created cookie instance + */ + public static HttpCookieBuilder serverCookie(final String name, final String value) { + + return new HttpCookieBuilder() { + + private int maxAge = -1; + + private String domain; + + private String path; + + private boolean secure; + + private boolean httpOnly; + + + @Override + public HttpCookieBuilder maxAge(int maxAge) { + this.maxAge = maxAge; + return this; + } + + @Override + public HttpCookieBuilder domain(String domain) { + this.domain = domain; + return this; + } + + @Override + public HttpCookieBuilder path(String path) { + this.path = path; + return this; + } + + @Override + public HttpCookieBuilder secure() { + this.secure = true; + return this; + } + + @Override + public HttpCookieBuilder httpOnly() { + this.httpOnly = true; + return this; + } + + @Override + public HttpCookie build() { + return new HttpCookie(name, value, this.maxAge, this.domain, this.path, + this.secure, this.httpOnly); + } + }; } /** - * Return true if the "HttpOnly" attribute of the cookie is present. - * @see http://www.owasp.org/index.php/HTTPOnly + * A builder for a server-defined HttpCookie with attributes. */ - public boolean isHttpOnly() { - return this.httpOnly; + public interface HttpCookieBuilder { + + /** + * Set the cookie "Max-Age" attribute in seconds. + * + *

A positive value indicates when the cookie should expire relative + * to the current time. A value of 0 means the cookie should expire + * immediately. A negative value results in no "Max-Age" attribute in + * which case the cookie is removed when the browser is closed. + */ + HttpCookieBuilder maxAge(int maxAge); + + /** + * Set the cookie "Path" attribute. + */ + HttpCookieBuilder path(String path); + + /** + * Set the cookie "Domain" attribute. + */ + HttpCookieBuilder domain(String domain); + + /** + * Add the "Secure" attribute to the cookie. + */ + HttpCookieBuilder secure(); + + /** + * Add the "HttpOnly" attribute to the cookie. + * @see http://www.owasp.org/index.php/HTTPOnly + */ + HttpCookieBuilder httpOnly(); + + /** + * Create the HttpCookie. + */ + HttpCookie build(); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web-reactive/src/main/java/org/springframework/http/HttpHeaders.java index 26380c84f8..419e94b947 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/HttpHeaders.java @@ -28,7 +28,6 @@ import java.util.Date; import java.util.EnumSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -366,7 +365,7 @@ public class HttpHeaders implements MultiValueMap, Serializable private final Map> headers; - private final Map> cookies; + private final Map> cookies; /** @@ -377,11 +376,11 @@ public class HttpHeaders implements MultiValueMap, Serializable } /** - * Constructor with a map of HTTP cookies that enables lazy initialization - * of input cookies on first access of the map. - * @param inputCookies a Map with input cookies + * Constructor with a map of HTTP input cookies (e.g. cookies sent by client) + * that enables lazy initialization on first access of the map. + * @param inputCookies input cookies */ - public HttpHeaders(Map> inputCookies) { + public HttpHeaders(Map> inputCookies) { this(new LinkedCaseInsensitiveMap>(8, Locale.ENGLISH), inputCookies, false); Assert.notNull(cookies, "'inputCookies' is required."); } @@ -389,7 +388,7 @@ public class HttpHeaders implements MultiValueMap, Serializable /** * Private constructor that can create read-only {@code HttpHeader} instances. */ - private HttpHeaders(Map> headers, Map> cookies, + private HttpHeaders(Map> headers, Map> cookies, boolean readOnly) { Assert.notNull(headers, "'headers' must not be null"); @@ -405,7 +404,7 @@ public class HttpHeaders implements MultiValueMap, Serializable } else { this.headers = headers; - this.cookies = (cookies != null ? cookies : new LinkedHashMap<>()); + this.cookies = (cookies != null ? cookies : new LinkedCaseInsensitiveMap<>()); } } @@ -722,13 +721,13 @@ public class HttpHeaders implements MultiValueMap, Serializable } /** - * Add an HTTP cookie. Supported only when writing output cookies. + * Add an HTTP cookie. */ public void addCookie(HttpCookie cookie) { String name = cookie.getName(); - Set set = this.cookies.get(name); + List set = this.cookies.get(name); if (set == null) { - set = new LinkedHashSet<>(); + set = new ArrayList<>(); this.cookies.put(name, set); } set.add(cookie); @@ -738,7 +737,7 @@ public class HttpHeaders implements MultiValueMap, Serializable * Return a map with {@link HttpCookie}s. When reading input cookies this map * cannot be modified. When writing output cookies, this map is mutable. */ - public Map> getCookies() { + public Map> getCookies() { return this.cookies; } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java index 24eeeb61c1..ebc5641cb1 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpRequest.java @@ -18,12 +18,13 @@ package org.springframework.http.server.reactive; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpCookie; +import org.springframework.http.HttpHeaders; +import org.springframework.util.LinkedCaseInsensitiveMap; /** * Common base class for {@link ServerHttpRequest} implementations. @@ -78,20 +79,20 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest { * first access to cookies via {@link #getHeaders()} and then cached. * @param cookies the map to add cookies to */ - protected abstract void initCookies(Map> cookies); + protected abstract void initCookies(Map> cookies); /** * Read-only map of input cookies with lazy initialization. */ - private class HttpCookieInputMap implements Map> { + private class HttpCookieInputMap implements Map> { - private Map> cookies; + private Map> cookies; - private Map> getCookies() { + private Map> getCookies() { if (this.cookies == null) { - this.cookies = new LinkedHashMap<>(); + this.cookies = new LinkedCaseInsensitiveMap<>(); initCookies(this.cookies); } return this.cookies; @@ -118,7 +119,7 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest { } @Override - public Set get(Object key) { + public List get(Object key) { return getCookies().get(key); } @@ -128,33 +129,33 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest { } @Override - public Collection> values() { + public Collection> values() { return getCookies().values(); } @Override - public Set>> entrySet() { + public Set>> entrySet() { return getCookies().entrySet(); } @Override - public Set put(String key, Set value) { - throw new UnsupportedOperationException("Read-only map of cookies."); + public List put(String key, List value) { + throw new UnsupportedOperationException("Can't modify client sent cookies."); } @Override - public Set remove(Object key) { - throw new UnsupportedOperationException("Read-only map of cookies."); + public List remove(Object key) { + throw new UnsupportedOperationException("Can't modify client sent cookies."); } @Override - public void putAll(Map> m) { - throw new UnsupportedOperationException("Read-only map of cookies."); + public void putAll(Map> map) { + throw new UnsupportedOperationException("Can't modify client sent cookies."); } @Override public void clear() { - throw new UnsupportedOperationException("Read-only map of cookies."); + throw new UnsupportedOperationException("Can't modify client sent cookies."); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java index 4ae9fc9f0a..9cf3260bb8 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java @@ -18,8 +18,8 @@ package org.springframework.http.server.reactive; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; +import java.util.List; import java.util.Map; -import java.util.Set; import reactor.Flux; import reactor.io.buffer.Buffer; @@ -68,7 +68,7 @@ public class ReactorServerHttpRequest extends AbstractServerHttpRequest { } @Override - protected void initCookies(Map> cookies) { + protected void initCookies(Map> cookies) { // https://github.com/reactor/reactor/issues/614 } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpRequest.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpRequest.java index 3e6c541f66..aa72c3f728 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpRequest.java @@ -19,9 +19,9 @@ package org.springframework.http.server.reactive; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; -import java.util.LinkedHashSet; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.Set; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.http.cookie.Cookie; @@ -74,20 +74,15 @@ public class RxNettyServerHttpRequest extends AbstractServerHttpRequest { } @Override - protected void initCookies(Map> map) { + protected void initCookies(Map> map) { for (String name : this.request.getCookies().keySet()) { - Set set = map.get(name); - if (set == null) { - set = new LinkedHashSet<>(); - map.put(name, set); + List list = map.get(name); + if (list == null) { + list = new ArrayList<>(); + map.put(name, list); } for (Cookie cookie : this.request.getCookies().get(name)) { - set.add(new HttpCookie(name, cookie.value()) - .setDomain(cookie.domain()) - .setPath(cookie.path()) - .setMaxAge(cookie.maxAge()) - .setSecure(cookie.isSecure()) - .setHttpOnly(cookie.isHttpOnly())); + list.add(HttpCookie.clientCookie(name, cookie.value())); } } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpResponse.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpResponse.java index 467c1d6dfd..863d71f5ca 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpResponse.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/RxNettyServerHttpResponse.java @@ -83,9 +83,11 @@ public class RxNettyServerHttpResponse extends AbstractServerHttpResponse { for (String name : getHeaders().getCookies().keySet()) { for (HttpCookie httpCookie : getHeaders().getCookies().get(name)) { Cookie cookie = new DefaultCookie(name, httpCookie.getValue()); + if (httpCookie.getMaxAge() > -1) { + cookie.setMaxAge(httpCookie.getMaxAge()); + } cookie.setDomain(httpCookie.getDomain()); cookie.setPath(httpCookie.getPath()); - cookie.setMaxAge(httpCookie.getMaxAge()); cookie.setSecure(httpCookie.isSecure()); cookie.setHttpOnly(httpCookie.isHttpOnly()); this.response.addCookie(cookie); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpRequest.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpRequest.java index 867c9356a2..6dd59e9379 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpRequest.java @@ -20,10 +20,10 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.Enumeration; -import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; -import java.util.Set; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; @@ -111,20 +111,15 @@ public class ServletServerHttpRequest extends AbstractServerHttpRequest { } @Override - protected void initCookies(Map> map) { + protected void initCookies(Map> map) { for (Cookie cookie : this.request.getCookies()) { String name = cookie.getName(); - Set set = map.get(name); - if (set == null) { - set = new LinkedHashSet<>(); - map.put(name, set); + List list = map.get(name); + if (list == null) { + list = new ArrayList<>(); + map.put(name, list); } - set.add(new HttpCookie(name, cookie.getValue()) - .setDomain(cookie.getDomain()) - .setPath(cookie.getPath()) - .setMaxAge(cookie.getMaxAge() == -1 ? Long.MIN_VALUE : cookie.getMaxAge()) - .setHttpOnly(cookie.isHttpOnly()) - .setSecure(cookie.getSecure())); + list.add(HttpCookie.clientCookie(name, cookie.getValue())); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java index a4e7e91446..53f5dcc349 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/ServletServerHttpResponse.java @@ -91,13 +91,15 @@ public class ServletServerHttpResponse extends AbstractServerHttpResponse { for (String name : getHeaders().getCookies().keySet()) { for (HttpCookie httpCookie : getHeaders().getCookies().get(name)) { Cookie cookie = new Cookie(name, httpCookie.getValue()); + if (httpCookie.getMaxAge() > -1) { + cookie.setMaxAge(httpCookie.getMaxAge()); + } if (httpCookie.getDomain() != null) { cookie.setDomain(httpCookie.getDomain()); } if (httpCookie.getPath() != null) { cookie.setPath(httpCookie.getPath()); } - cookie.setMaxAge(httpCookie.getMaxAge() == Long.MIN_VALUE ? -1 : (int) httpCookie.getMaxAge()); cookie.setSecure(httpCookie.isSecure()); cookie.setHttpOnly(httpCookie.isHttpOnly()); this.response.addCookie(cookie); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java index 53013fbe54..6f8c35b7ff 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpRequest.java @@ -19,9 +19,9 @@ package org.springframework.http.server.reactive; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; -import java.util.LinkedHashSet; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.Set; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.Cookie; @@ -79,20 +79,15 @@ public class UndertowServerHttpRequest extends AbstractServerHttpRequest { } @Override - protected void initCookies(Map> map) { + protected void initCookies(Map> map) { for (String name : this.exchange.getRequestCookies().keySet()) { - Set set = map.get(name); - if (set == null) { - set = new LinkedHashSet<>(); - map.put(name, set); + List list = map.get(name); + if (list == null) { + list = new ArrayList<>(); + map.put(name, list); } Cookie cookie = this.exchange.getRequestCookies().get(name); - set.add(new HttpCookie(name, cookie.getValue()) - .setDomain(cookie.getDomain()) - .setPath(cookie.getPath()) - .setMaxAge(cookie.getMaxAge() != null ? cookie.getMaxAge() : Long.MIN_VALUE) - .setSecure(cookie.isSecure()) - .setHttpOnly(cookie.isHttpOnly())); + list.add(HttpCookie.clientCookie(name, cookie.getValue())); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java index 27c38342f8..3057396587 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/server/reactive/UndertowServerHttpResponse.java @@ -83,9 +83,11 @@ public class UndertowServerHttpResponse extends AbstractServerHttpResponse { for (String name : getHeaders().getCookies().keySet()) { for (HttpCookie httpCookie : getHeaders().getCookies().get(name)) { Cookie cookie = new CookieImpl(name, httpCookie.getValue()); + if (httpCookie.getMaxAge() > -1) { + cookie.setMaxAge(httpCookie.getMaxAge()); + } cookie.setDomain(httpCookie.getDomain()); cookie.setPath(httpCookie.getPath()); - cookie.setMaxAge(httpCookie.getMaxAge() == Long.MIN_VALUE ? null : (int) httpCookie.getMaxAge()); cookie.setSecure(httpCookie.isSecure()); cookie.setHttpOnly(httpCookie.isHttpOnly()); this.exchange.getResponseCookies().putIfAbsent(name, cookie); diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/CookieIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/CookieIntegrationTests.java index 6a1dccb4ae..dbb866219e 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/CookieIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/CookieIntegrationTests.java @@ -19,7 +19,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import org.junit.After; import org.junit.Before; @@ -102,32 +101,29 @@ public class CookieIntegrationTests { ResponseEntity response = new RestTemplate().exchange( RequestEntity.get(url).header("Cookie", header).build(), Void.class); - Map> requestCookies = this.cookieHandler.requestCookies; + Map> requestCookies = this.cookieHandler.requestCookies; assertEquals(2, requestCookies.size()); - Set set = requestCookies.get("SID"); - assertEquals(1, set.size()); - assertEquals("31d4d96e407aad42", set.iterator().next().getValue()); + List list = requestCookies.get("SID"); + assertEquals(1, list.size()); + assertEquals("31d4d96e407aad42", list.iterator().next().getValue()); - set = requestCookies.get("lang"); - assertEquals(1, set.size()); - assertEquals("en-US", set.iterator().next().getValue()); + list = requestCookies.get("lang"); + assertEquals(1, list.size()); + assertEquals("en-US", list.iterator().next().getValue()); List headerValues = response.getHeaders().get("Set-Cookie"); assertEquals(2, headerValues.size()); - List parts = splitCookieHeader(headerValues.get(0)); - assertThat(parts, containsInAnyOrder(equalTo("SID=31d4d96e407aad42"), - equalToIgnoringCase("Path=/"), equalToIgnoringCase("Secure"), - equalToIgnoringCase("HttpOnly"))); + assertThat(splitCookie(headerValues.get(0)), containsInAnyOrder(equalTo("SID=31d4d96e407aad42"), + equalToIgnoringCase("Path=/"), equalToIgnoringCase("Secure"), equalToIgnoringCase("HttpOnly"))); - parts = splitCookieHeader(headerValues.get(1)); - assertThat(parts, containsInAnyOrder(equalTo("lang=en-US"), + assertThat(splitCookie(headerValues.get(1)), containsInAnyOrder(equalTo("lang=en-US"), equalToIgnoringCase("Path=/"), equalToIgnoringCase("Domain=example.com"))); } // No client side HttpCookie support yet - private List splitCookieHeader(String value) { + private List splitCookie(String value) { List list = new ArrayList<>(); for (String s : value.split(";")){ list.add(s.trim()); @@ -138,7 +134,7 @@ public class CookieIntegrationTests { private class CookieHandler implements HttpHandler { - private Map> requestCookies; + private Map> requestCookies; @Override @@ -147,10 +143,10 @@ public class CookieIntegrationTests { this.requestCookies = request.getHeaders().getCookies(); this.requestCookies.size(); // Cause lazy loading - response.getHeaders().addCookie(new HttpCookie("SID", "31d4d96e407aad42") - .setPath("/").setHttpOnly(true).setSecure(true)); - response.getHeaders().addCookie(new HttpCookie("lang", "en-US") - .setDomain("example.com").setPath("/")); + response.getHeaders().addCookie(HttpCookie.serverCookie("SID", "31d4d96e407aad42") + .path("/").secure().httpOnly().build()); + response.getHeaders().addCookie(HttpCookie.serverCookie("lang", "en-US") + .domain("example.com").path("/").build()); response.writeHeaders(); return Mono.empty();