spring-boot icon indicating copy to clipboard operation
spring-boot copied to clipboard

Provide a mechanism for easily configuring global client HTTP request factory settings

Open wilkinsona opened this issue 2 years ago • 6 comments

We use ClientHttpRequestFactorySettings when creating RestTemplateBuilder, RestClient.Builder, and indirectly TestRestTemplate. It would be useful to have a mechanism for changing the settings for each of these three usages in a single place, perhaps by using configuration properties. In addition to those settings, it should also be possible specify the type of ClientHttpRequestFactory to use. This would be useful when you want to override the class path-based auto-detection.

wilkinsona avatar Jul 06 '23 16:07 wilkinsona

We think that the ability to easily specify the ClientHttpRequestFactory is a prerequisite for adding the new JdkClientHttpRequestFactory to the auto-detection due to it always being available yet behaving differently to SimpleClientHttpRequestFactory.

wilkinsona avatar Jul 06 '23 16:07 wilkinsona

Hi @wilkinsona, possible first-timer contribution here! Do you mind I pick this issue up? Also, would it be better for the auto-configuration to provide a bean for the ClientHttpRequestFactorySettings with the added field to define the ClientHttpRequestFactory to use or to provide the ClientHttpRequestFactory itself and maintain the ClientHttpRequestFactorySettings structure as is?

be0x74a avatar Jul 09 '23 15:07 be0x74a

Thanks for the offer, @be0x74a, but we're not exactly sure what we want to do here just yet. I probably should have labelled the issue as pending design work when I opened it. I've done that now.

wilkinsona avatar Jul 09 '23 20:07 wilkinsona

Ah alright, thanks for letting me know @wilkinsona! Will keep an eye on it, for when it gets decided

be0x74a avatar Jul 09 '23 20:07 be0x74a

I did something similar to this in the new Spring Cloud Gateway MVC Server

        GatewayMvcProperties.HttpClient properties = gatewayMvcProperties.getHttpClient();


        SslBundle sslBundle = null;
        if (StringUtils.hasText(properties.getSslBundle())) {
            sslBundle = sslBundles.getBundle(properties.getSslBundle());
        }
        ClientHttpRequestFactorySettings settings = new ClientHttpRequestFactorySettings(properties.getConnectTimeout(),
                properties.getReadTimeout(), sslBundle);


        if (properties.getType() == GatewayMvcProperties.HttpClientType.JDK) {
            // TODO: customize restricted headers
            String restrictedHeaders = System.getProperty("jdk.httpclient.allowRestrictedHeaders");
            if (!StringUtils.hasText(restrictedHeaders)) {
                System.setProperty("jdk.httpclient.allowRestrictedHeaders", "host");
            }
            else if (StringUtils.hasText(restrictedHeaders) && !restrictedHeaders.contains("host")) {
                System.setProperty("jdk.httpclient.allowRestrictedHeaders", restrictedHeaders + ",host");
            }


            return ClientHttpRequestFactories.get(JdkClientHttpRequestFactory.class, settings);
        }


        // Autodetect
        return ClientHttpRequestFactories.get(settings);

https://github.com/spring-cloud/spring-cloud-gateway/blob/5202c773fd796e7f5efbeea461854bfb91e561f6/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java#L73-L96

spencergibb avatar Jul 09 '23 22:07 spencergibb

I stumbled upon this issue because I was wondering why ClientHttpRequestFactories.get(ClientHttpRequestFactorySettings) still returns SimpleClientHttpRequestFactory instead of JdkClientHttpRequestFactory by default. And I just wanted to mention that ClientHttpRequestFactories is also used in HttpWebServiceMessageSenderBuilder.

sephiroth-j avatar Sep 23 '23 16:09 sephiroth-j