Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ public static long deltaSeconds(final String s) {
return ageValue;
} catch (final NumberFormatException ignore) {
}
return 0;
// A value that is not a valid delta-seconds token is invalid and must be treated as absent (RFC 9111 4.2.1),
// not folded into a usable 0 which would look like a genuine directive.
return -1;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ void testParseSMaxAge() {
void testParseInvalidCacheValue() {
final Header header = new BasicHeader("Cache-Control", "max-age=invalid");
final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
assertEquals(0L, cacheControl.getMaxAge());
// A malformed delta-seconds value is invalid and must be treated as absent (-1), not a usable 0.
assertEquals(-1L, cacheControl.getMaxAge());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void testParseDeltaSeconds() {
Assertions.assertEquals(-1L, CacheSupport.deltaSeconds("-100"));
Assertions.assertEquals(-1L, CacheSupport.deltaSeconds(""));
Assertions.assertEquals(-1L, CacheSupport.deltaSeconds(null));
Assertions.assertEquals(0L, CacheSupport.deltaSeconds("huh?"));
Assertions.assertEquals(-1L, CacheSupport.deltaSeconds("huh?"));
Assertions.assertEquals(2147483648L, CacheSupport.deltaSeconds("2147483648"));
Assertions.assertEquals(2147483648L, CacheSupport.deltaSeconds("2147483649"));
Assertions.assertEquals(2147483648L, CacheSupport.deltaSeconds("214748364712"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,20 @@ void testSMaxageWithAuthorizationIsCacheable() {
"Response with s-maxage and Authorization header should be cacheable in shared cache.");
}

@Test
void testMalformedSMaxageWithAuthorizationNotCacheableBySharedCache() {
request = new BasicHttpRequest("GET", "/resource");
request.setHeader(HttpHeaders.AUTHORIZATION, "Basic dXNlcjpwYXNzd2Q=");
response.setHeader("Expires", DateUtils.formatStandardDate(tenSecondsFromNow));
response.setHeader("Cache-Control", "s-maxage=invalid");
// Parse the actual header so the malformed value is handled the way it is on the wire.
responseCacheControl = CacheControlHeaderParser.INSTANCE.parse(response);

final boolean isCacheable = policy.isResponseCacheable(requestCacheControl, responseCacheControl, request, response);
assertFalse(isCacheable,
"Response to an Authorization request with a malformed s-maxage must not be stored by a shared cache.");
}

@Test
void testNoDirectivesWithAuthorizationNotCacheable() {
request = new BasicHttpRequest("GET", "/resource");
Expand Down
Loading