Skip to content

RestTemplateBuilder custom request factory, cannot pass client and keep default sslbundle configuration #36594

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
krodyrobi opened this issue Jul 26, 2023 · 3 comments
Labels
status: superseded An issue that has been superseded by another theme: http-client-config Issues related to configuration of HTTP clients theme: ssl Issues related to ssl support type: bug A general bug

Comments

@krodyrobi
Copy link

By default ClientHttpRequestFactories created using RestTemplateBuilder.requestFactory(settings) will have only 3 properties applicable sslbundle and some timeouts.

If I need to have both ssl and for instance configure some more flags on the specific client I cannot use the factory, and I am forced to either duplicate the FactoryLogic (client is not protected so extending does not help) or duplicate the property / ssl configuration.

builder
   .setSslBundle(bundles.getBundle("some"))
   .requestFactory((settings) -> {
       // no way to pass client here
       return ClientHttpRequestFactories.get(OkHttp3ClientHttpRequestFactory.class, settings);
    })
    .build()
builder
    .setSslBundle(bundles.getBundle("some"))
   .requestFactory((settings) -> {
       var clientBuilder = new OkHttpClient.Builder();
       clientBuilder.callTimeout(Duration.ofSeconds(3));

       // Adapted from ClientHttpRequestFactories.OkHttp
       Assert.state(settings.bufferRequestBody() == null, 
            () -> "OkHttp3ClientHttpRequestFactory does not support request body buffering");
       PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
       map.from(settings::connectTimeout).to(clientBuilder::connectTimeout);
       map.from(settings::readTimeout).to(clientBuilder::readTimeout);

       SslBundle sslBundle = settings.sslBundle();
       if (sslBundle != null) {
           Assert.state(!sslBundle.getOptions().isSpecified(), "SSL Options cannot be specified with OkHttp");
           SSLSocketFactory socketFactory = sslBundle.createSslContext().getSocketFactory();
           TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers();
            Assert.state(trustManagers.length == 1,
               "Trust material must be provided in the SSL bundle for OkHttp3ClientHttpRequestFactory");
            clientBuilder
                .sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]);

       }
       return new OkHttp3ClientHttpRequestFactory(clientBuilder.build());
  })
  .build();
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 26, 2023
@wilkinsona
Copy link
Member

See also #36263 and #36266.

@krodyrobi
Copy link
Author

krodyrobi commented Jul 27, 2023

As a side note, the factory cleans up it's own created client but, if someone uses the property mutators it creates a new one, only the last client built will ever be cleaned up.

@philwebb philwebb added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 7, 2023
@philwebb philwebb added this to the 3.1.x milestone Nov 7, 2023
@scottfrederick scottfrederick added the theme: ssl Issues related to ssl support label Nov 16, 2023
@scottfrederick scottfrederick added the theme: http-client-config Issues related to configuration of HTTP clients label Jan 9, 2024
@wilkinsona wilkinsona modified the milestones: 3.1.x, 3.2.x May 20, 2024
@philwebb philwebb modified the milestones: 3.2.x, 3.3.x Nov 20, 2024
@philwebb
Copy link
Member

As of Spring Boot 3.4 I think the new ClientHttpRequestFactoryBuilder will allow you do what you want (although OKHttp is no longer supported).

ClientHttpRequestFactoryBuilder requestFactoryBuilder = ClientHttpRequestFactoryBuilder
    .httpComponents()
    .withDefaultRequestConfigCustomizer((builder) -> builder.setConnectionRequestTimeout(Timeout.ONE_MILLISECOND));
restTemplateBuilder.requestFactoryBuilder(requestFactoryBuilder).build();

Given the age of this issue, I'm going to close it in 3.3 and suggest that folks either copy/paste the code or upgrade.

@philwebb philwebb closed this as not planned Won't fix, can't repro, duplicate, stale May 15, 2025
@philwebb philwebb added the status: superseded An issue that has been superseded by another label May 15, 2025
@philwebb philwebb removed this from the 3.3.x milestone May 15, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
status: superseded An issue that has been superseded by another theme: http-client-config Issues related to configuration of HTTP clients theme: ssl Issues related to ssl support type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants