From 13aba4a8454b75010ceeddbc9b65a6134e0b5fe0 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Thu, 19 Feb 2026 14:46:42 +0100 Subject: [PATCH] Treat Max-Age<=0 as immediate expiry Align strict Max-Age parsing with RFC 6265 user-agent processing. Non-positive delta-seconds now expire cookies immediately instead of being rejected as malformed. --- .../client5/http/impl/cookie/BasicMaxAgeHandler.java | 7 ++++--- .../impl/cookie/TestBasicCookieAttribHandlers.java | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/cookie/BasicMaxAgeHandler.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/cookie/BasicMaxAgeHandler.java index e2c9270630..08ebc1d01a 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/cookie/BasicMaxAgeHandler.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/cookie/BasicMaxAgeHandler.java @@ -69,9 +69,10 @@ public void parse(final SetCookie cookie, final String value) throw new MalformedCookieException ("Invalid 'max-age' attribute: " + value); } - if (age < 0) { - throw new MalformedCookieException ("Negative 'max-age' attribute: " - + value); + if (age <= 0) { + // RFC 6265 user-agent processing: delta-seconds <= 0 means immediate expiry. + cookie.setExpiryDate(Instant.EPOCH); + return; } cookie.setExpiryDate(Instant.now().plusSeconds(age)); } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java index 2a9cc7d20e..3b0d53c843 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java @@ -270,6 +270,17 @@ void testBasicMaxAgeParse() throws Exception { Assertions.assertNotNull(cookie.getExpiryInstant()); } + @Test + void testBasicMaxAgeParseDeleteNow() throws Exception { + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + final CookieAttributeHandler h = BasicMaxAgeHandler.INSTANCE; + h.parse(cookie, "0"); + Assertions.assertEquals(Instant.EPOCH, cookie.getExpiryInstant()); + final BasicClientCookie cookie2 = new BasicClientCookie("name", "value"); + h.parse(cookie2, "-1"); + Assertions.assertEquals(Instant.EPOCH, cookie2.getExpiryInstant()); + } + @Test void testBasicMaxAgeParseInvalid() { final BasicClientCookie cookie = new BasicClientCookie("name", "value");