Context:
I have a back-end Spring-Boot micro-service (SB v3.5.6) which connect to several external resources.
My micro-service is deployed in a k8s cluster and uses Istio as internal k8s proxy.
For Internet access we have to use a specific proxy: let's name it "proxy.us.aws.comp.net:3128"
Some of these resource are in our VPC and can be accessed directy and others are in public Internet (SAAS services).
The domain used for all internal resources in the same VPC is: <subdomains>.comp.net
Exemple of configuration:
# internal servers
## internal API
internal.api.base.url: https://specific-internal.api.comp.net:8709/internal-api/v2/
## External Service
external.api.base.url: https://an-external-rest.api.domain.com/the-api/v1/
To connect to these API's, I am creating a WebClient using spring-boot-starter-webflux with the default configuration (netty) and I have declared the WebClientConfig class like this:
@Configuration
public class WebClientConfig {
// Timeout : 2 minute for all http connections
private int timeout = 120 \* 1000;
// ...
// 2 WebClient and 2 ClientHttpConnector Beans declared with and without proxy.
// ...
@Bean
public HttpClient httpClientWithProxy() {
ConnectionProvider connProvider = ConnectionProvider
.builder("webclient-conn-pool")
// Keep Alive Strategy
.maxIdleTime(Duration.ofMillis(120000))
.pendingAcquireTimeout(Duration.ofMillis(90000))
.build();
return HttpClient.create(connProvider)
// Connection timeout
.doOnConnected(conn -\> conn
.addHandlerLast(new ReadTimeoutHandler(timeout, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(timeout, TimeUnit.MILLISECONDS)))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.proxyWithSystemProperties();
}
@Bean
public HttpClient httpClientDirect() {
ConnectionProvider connProvider = ConnectionProvider
.builder("webclient-conn-pool")
// Keep Alive Strategy
.maxIdleTime(Duration.ofMillis(120000))
.pendingAcquireTimeout(Duration.ofMillis(90000))
.build();
return HttpClient.create(connProvider)
// Connection timeout
.doOnConnected(conn -\> conn
.addHandlerLast(new ReadTimeoutHandler(timeout, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(timeout, TimeUnit.MILLISECONDS)))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
.proxyWithSystemProperties();
}
}
This is working well like this.
Now I wanted to check if it's possible to use only the proxified HttpClient and use the no-proxy properties to bypass the proxy.
If I use only the httpClientWithProxy and even I add the following properties in my JVM (I am using JIB maven plugin):
<jvmFlags\>
<jvmFlag\>-Dhttps.proxyHost=proxy.us.aws.comp.net:3128\</jvmFlag\>
<jvmFlag\>-Dhttps.proxyPort=3128\</jvmFlag\>
<jvmFlag\>-Dhttp.proxyHost=proxy.us.aws.comp.net:3128\</jvmFlag\>
<jvmFlag\>-Dhttp.proxyPort=3128\</jvmFlag\>
<jvmFlag\>-Dhttp.nonProxyHosts="localhost|127.0.0.1|192.168.*|*.comp.net|*.svc.cluster.local"\</jvmFlag\>
</jvmFlags\>
It seems the nonProxyHost is not enforced as it continue to use the proxy even when trying to reach the internal API at specific-internal.api.comp.net
I would expect the pattern "*.comp.net" will bypass the proxy but it seems not working.
I also found an old similar bug which seems already fixed on Reactor Netty side.
Perhaps I misunderstood how work the nonProxyHost property, but for me it means it should not send the request to proxy.us.aws.comp.net like it is direct but I see in the logs that it goes through.
I am staying with the double config but I am wondering why by defining proxy and exception it's not working the same way.
I also saw this old question but one answer is exactly mentioning the proxyWithSystemProperties() way.
1 Answer 1
"The pattern used in http.nonProxyHosts is not compatible with regex", see another GitHub issue about wildcard: https://github.com/reactor/reactor-netty/issues/1861