Search code examples
spring-bootcookiesattributeshttpclientpaypal-ipn

Invalid cookie header: Invalid 'expires' attribute


I am using a standard RestTemplate of Spring boot 2.6.7, which corresponds to org.apache.httpcomponents -> httpclient -> 4.5.13.

Calling one public API causes some warnings to be present in the logs. The logger appears to be from httpclient from apache: org.apache.http.client.protocol.ResponseProcessCookies The warning is:

Invalid cookie header: "Set-Cookie: ts=foo; Path=/; Domain=paypal.com; 
Expires=Sat, 21 Feb 2026 14:43:55 GMT; HttpOnly; Secure". 
Invalid 'expires' attribute: Sat, 21 Feb 2026 14:43:55 GMT

I checked the source code of apache http client:

  • The interceptor org.apache.http.client.protocol.RequestAddCookies influences the org.apache.http.client.protocol.ResponseProcessCookies one
  • In the end it all falls down to using the org.apache.http.impl.cookie.DefaultCookieSpec
  • which instantiates a netscapeDraft with NetscapeDraftSpec.EXPIRES_PATTERN, which is EEE, dd-MMM-yy HH:mm:ss z
  • so when the DefaultCookieSpec sees the attribute expires it goes and tries to parse it via the above mentioned pattern, which is legacy and failing (see below a screenshot from apache httpclient lib): enter image description here

I don't understand how come the default settings are not enough to have a perfectly conform date to be able to parsed properly. The PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz" would be working with Sat, 21 Feb 2026 14:43:55 GMT, but it is not used as default. In order to make it working I have to customize the cookie parsing explicitly, which appears ugly to me:

new RestTemplateBuilder()
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory(
        HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec("fixPaypalExpires").build())
                .setDefaultCookieSpecRegistry(CookieSpecRegistries.createDefaultBuilder()
                        .register("fixPaypalExpires",
                                new DefaultCookieSpecProvider(
                                        CompatibilityLevel.DEFAULT,
                                        PublicSuffixMatcherLoader.getDefault(),
                                        new String[]{"EEE, dd MMM yyyy HH:mm:ss z"},
                                        false))
                        .build())
                .build()))
.build();

Or maybe I can use one of the pre-defined cookie spec providers, but still the default should work out of the box or? What do you think?

Thanks in advance


Solution

  • Looks like acceptably answered here.

    Even it is slightly about something else, it suggests a fairly acceptable workaround:

    HttpClient httpClient = HttpClients.custom()
        .setDefaultRequestConfig(RequestConfig.custom()
                .setCookieSpec(CookieSpecs.STANDARD).build())
        .build();