This answer is not directly related to the OP, but to help those looking for a solution to the problem. This is the first result on Google when searching Invalid expires attribute
.
I am using Resteasy as a transitive dependency of Keycloak Admin REST Client.
The problem is resteasy-client
does not provide an easy way to configure the Apache HttpClient
HttpClient#RequestConfig#CookieSpec
. See the default ClientHttpEngineBuilder
used by resteasy-client
ClientHttpEngineBuilder43.
To fix it, since the ClientHttpEngineBuilder43#createEngine
method is protected
, I have extended the class and specified the suggested CookieSpecs.STANDARD
:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpHost;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.jboss.resteasy.client.jaxrs.ClientHttpEngine;
import org.jboss.resteasy.client.jaxrs.ClientHttpEngineBuilder43;
public class StandardCookieSpecClientHttpEngineBuilder extends ClientHttpEngineBuilder43 {
@Override
protected ClientHttpEngine createEngine(
HttpClientConnectionManager cm,
Builder rcBuilder,
HttpHost defaultProxy,
int responseBufferSize,
HostnameVerifier verifier,
SSLContext context) {
// CookieSpecs.DEFAULT does not handle the latest RFC correctly
// <https://mcmap.net/q/240158/-fixing-httpclient-warning-quot-invalid-expires-attribute-quot-using-fluent-api>
rcBuilder.setCookieSpec(CookieSpecs.STANDARD);
return super.createEngine(cm, rcBuilder, defaultProxy, responseBufferSize, verifier, context);
}
}
Then, the corresponding ResteasyClient
and Keycloak
are built as:
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class KeycloakConfig {
@Bean
public Keycloak keycloak() {
return KeycloakBuilder.builder()
// ... Some other configuration to the builder
.resteasyClient(buildResteasyClient())
.build();
}
private ResteasyClient buildResteasyClient() {
ResteasyClientBuilder resteasyClientBuilder = new ResteasyClientBuilder();
// ... Some other configuration to the client builder
return resteasyClientBuilder
.httpEngine(
new StandardCookieSpecClientHttpEngineBuilder()
.resteasyClientBuilder(resteasyClientBuilder)
.build())
.build();
}
}