Skip to content
Commits on Source (3)
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-benchmarks</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow Benchmarks</name>
......@@ -41,27 +41,6 @@
<artifactId>undertow-core</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-websockets-jsr</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-nio</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
......@@ -72,22 +51,12 @@
<artifactId>jmh-core</artifactId>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow Core</name>
......
......@@ -645,7 +645,7 @@ public final class HttpServerExchange extends AbstractAttachable {
*/
public String getHostAndPort() {
String host = requestHeaders.getFirst(Headers.HOST);
if (host == null) {
if (host == null || "".equals(host.trim())) {
InetSocketAddress address = getDestinationAddress();
host = NetworkUtils.formatPossibleIpv6Address(address.getHostString());
int port = address.getPort();
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<artifactId>undertow-coverage-report</artifactId>
<name>Undertow Test Coverage Report</name>
......
undertow (2.0.28-1) unstable; urgency=medium
* New upstream version 2.0.28.
-- Markus Koschany <apo@debian.org> Sun, 17 Nov 2019 14:41:48 +0100
undertow (2.0.27-1) unstable; urgency=medium
* New upstream version 2.0.27.
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-dist</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow: Distribution</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-examples</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow Examples</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>karaf</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<packaging>pom</packaging>
<name>Undertow Karaf Features</name>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parser-generator</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow Parser Generator</name>
<description>An annotation processor that is used to generate the HTTP parser</description>
......
......@@ -28,7 +28,7 @@
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow</name>
<description>Undertow</description>
......
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-servlet</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow Servlet</name>
......
......@@ -88,6 +88,7 @@ public final class HttpServletResponseImpl implements HttpServletResponse {
private String contentType;
private String charset;
private Supplier<Map<String, String>> trailerSupplier;
// a map of cookie name -> a map of (cookie path + cookie domain) -> cookie
private Map<String, Map<String, Cookie>> duplicateCookies;
public HttpServletResponseImpl(final HttpServerExchange exchange, final ServletContextImpl servletContext) {
......@@ -113,27 +114,32 @@ public final class HttpServletResponseImpl implements HttpServletResponse {
if (exchange.getResponseCookies().containsKey(servletCookieAdaptor.getName())) {
final String cookieName = servletCookieAdaptor.getName();
final String path = servletCookieAdaptor.getPath();
final String domain = servletCookieAdaptor.getDomain();
final Cookie otherCookie = exchange.getResponseCookies().get(cookieName);
final String otherCookiePath = otherCookie.getPath();
// if both cookies have same path and name, overwrite previous cookie
if ((path == otherCookiePath) || (path != null && path.equals(otherCookiePath))) {
final String otherCookieDomain = otherCookie.getDomain();
// if both cookies have same path, name, and domain, overwrite previous cookie
if ((path == otherCookiePath || (path != null && path.equals(otherCookiePath))) &&
(domain == otherCookieDomain || (domain != null && domain.equals(otherCookieDomain)))) {
exchange.setResponseCookie(servletCookieAdaptor);
}
// else, create a duplicate cookie entry
else {
final Map<String, Cookie> cookiesByPath;
final Map<String, Cookie> cookiesByPathPlusDomain;
if (duplicateCookies == null) {
duplicateCookies = new TreeMap<>();
exchange.addResponseCommitListener(
new DuplicateCookieCommitListener());
}
if (duplicateCookies.containsKey(cookieName)) {
cookiesByPath = duplicateCookies.get(cookieName);
cookiesByPathPlusDomain = duplicateCookies.get(cookieName);
} else {
cookiesByPath = new TreeMap<>();
duplicateCookies.put(cookieName, cookiesByPath);
cookiesByPathPlusDomain = new TreeMap<>();
duplicateCookies.put(cookieName, cookiesByPathPlusDomain);
}
cookiesByPath.put(otherCookiePath == null ? "null" : otherCookiePath, otherCookie);
String pathPlusDomain = (otherCookiePath == null ? "null" : otherCookiePath) +
(otherCookieDomain == null? "null" : otherCookieDomain);
cookiesByPathPlusDomain.put(pathPlusDomain, otherCookie);
}
}
exchange.setResponseCookie(servletCookieAdaptor);
......
......@@ -35,14 +35,35 @@ public class DuplicateCookiesServlet extends HttpServlet {
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie1 = new Cookie("test", "test");
cookie1.setPath("/test");
Cookie cookie1 = new Cookie("test1", "test1");
cookie1.setPath("/test1_1");
Cookie cookie2 = new Cookie("test1", "test1");
cookie2.setPath("/test1_2");
Cookie cookie3 = new Cookie("test2", "test2");
cookie3.setPath("/test2");
Cookie cookie4 = new Cookie("test2", "test2");
cookie4.setPath("/test2");
cookie4.setDomain("www.domain2.com");
Cookie cookie5 = new Cookie("test3", "test3");
cookie5.setDomain("www.domain3-1.com");
Cookie cookie6 = new Cookie("test3", "test3");
cookie6.setDomain("www.domain3-2.com");
Cookie cookie7 = new Cookie("test3", "test3");
Cookie cookie2 = new Cookie("test", "test");
cookie2.setPath("/test2");
resp.addCookie(cookie1);
resp.addCookie(cookie2);
resp.addCookie(cookie3);
resp.addCookie(cookie4);
resp.addCookie(cookie5);
resp.addCookie(cookie6);
resp.addCookie(cookie7);
resp.getWriter().append("Served at: ").append(req.getContextPath());
}
......
......@@ -47,11 +47,34 @@ public class OverwriteCookiesServlet extends HttpServlet {
Cookie cookie4 = new javax.servlet.http.Cookie("test", "test4");
Cookie cookie5 = new javax.servlet.http.Cookie("test", "test5");
Cookie cookie6 = new javax.servlet.http.Cookie("test", "test6");
cookie6.setPath("/test");
cookie6.setDomain("www.domain.com");
Cookie cookie7 = new javax.servlet.http.Cookie("test", "test7");
cookie7.setPath("/test");
cookie7.setDomain("www.domain.com");
Cookie cookie8 = new javax.servlet.http.Cookie("test", "test8");
cookie8.setPath("/test");
cookie8.setDomain("www.domain.com");
Cookie cookie9 = new javax.servlet.http.Cookie("test", "test9");
cookie9.setDomain("www.domain.com");
Cookie cookie10 = new javax.servlet.http.Cookie("test", "test10");
cookie10.setDomain("www.domain.com");
resp.addCookie(cookie1);
resp.addCookie(cookie2);
resp.addCookie(cookie3);
resp.addCookie(cookie4);
resp.addCookie(cookie5);
resp.addCookie(cookie6);
resp.addCookie(cookie7);
resp.addCookie(cookie8);
resp.addCookie(cookie9);
resp.addCookie(cookie10);
// creating session -> additional jsessionid set-cookie
req.getSession().setAttribute("CleanSessions", true);
......
......@@ -18,6 +18,9 @@
package io.undertow.servlet.test.response.cookies;
import java.util.Arrays;
import java.util.Comparator;
import javax.servlet.ServletException;
import io.undertow.servlet.api.ServletInfo;
......@@ -89,9 +92,16 @@ public class ResponseCookiesTestCase {
assertEquals("Served at: /servletContext", response);
final Header[] setCookieHeaders = result.getHeaders("Set-Cookie");
assertEquals(2, setCookieHeaders.length);
assertEquals("test=test; path=/test", setCookieHeaders[0].getValue());
assertEquals("test=test; path=/test2", setCookieHeaders[1].getValue());
assertEquals(7, setCookieHeaders.length);
Arrays.sort(setCookieHeaders, Comparator.comparing(Object::toString));
assertEquals("test1=test1; path=/test1_1", setCookieHeaders[0].getValue());
assertEquals("test1=test1; path=/test1_2", setCookieHeaders[1].getValue());
assertEquals("test2=test2; path=/test2", setCookieHeaders[2].getValue());
assertEquals("test2=test2; path=/test2; domain=www.domain2.com", setCookieHeaders[3].getValue());
assertEquals("test3=test3", setCookieHeaders[4].getValue());
assertEquals("test3=test3; domain=www.domain3-1.com", setCookieHeaders[5].getValue());
assertEquals("test3=test3; domain=www.domain3-2.com", setCookieHeaders[6].getValue());
} finally {
client.getConnectionManager().shutdown();
}
......@@ -109,11 +119,15 @@ public class ResponseCookiesTestCase {
assertEquals("Served at: /servletContext", response);
final Header[] setCookieHeaders = result.getHeaders("Set-Cookie");
assertEquals(3, setCookieHeaders.length);
assertEquals("test=test2; path=/test", setCookieHeaders[0].getValue());
assertTrue("Header " + setCookieHeaders[1] + "didn't match expected regex",
setCookieHeaders[1].getValue().matches("JSESSIONID=.*; path=/servletContext"));
assertEquals("test=test5", setCookieHeaders[2].getValue());
assertEquals(5, setCookieHeaders.length);
Arrays.sort(setCookieHeaders, Comparator.comparing(Object::toString));
assertTrue("Header " + setCookieHeaders[0] + "didn't match expected regex",
setCookieHeaders[0].getValue().matches("JSESSIONID=.*; path=/servletContext"));
assertEquals("test=test10; domain=www.domain.com", setCookieHeaders[1].getValue());
assertEquals("test=test2; path=/test", setCookieHeaders[2].getValue());
assertEquals("test=test5", setCookieHeaders[3].getValue());
assertEquals("test=test8; path=/test; domain=www.domain.com", setCookieHeaders[4].getValue());
} finally {
client.getConnectionManager().shutdown();
}
......
......@@ -293,4 +293,11 @@
<Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"/>
<Class name="io.undertow.client.http.HttpClientConnection$ClientReadListener" />
</Match>
<!-- Comparison of cookies path and domain with == before invoking equals is necessary because
both could be null; only if the == fails we check for one of them != null && equals the other -->
<Match>
<Bug pattern="ES_COMPARING_STRINGS_WITH_EQ"/>
<Class name="io.undertow.servlet.spec.HttpServletResponseImpl"/>
<Method name="addCookie"/>
</Match>
</FindBugsFilter>
......@@ -25,12 +25,12 @@
<parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-parent</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
</parent>
<groupId>io.undertow</groupId>
<artifactId>undertow-websockets-jsr</artifactId>
<version>2.0.27.Final</version>
<version>2.0.28.Final</version>
<name>Undertow WebSockets JSR356 implementations</name>
......