【问题标题】:Proxy setting not working with Spring WebClient代理设置不适用于 Spring WebClient
【发布时间】:2020-02-29 12:31:46
【问题描述】:

我的以下 WebClient 在 Internet 连接下工作正常,但无法通过我们的代理连接。

WebClient webClient = WebClient.builder()
        .baseUrl("https://targetsite.com")
        .build();

webClient.post()
    .uri("/service/serviceName")
    .body(BodyInserters.fromObject(reqData))
    .retrieve()
    .bodyToMono(WebServiceResponse.class)

虽然事件,同一个客户端正在通过代理工作,如果我按如下所述设置它,

HttpClient httpClient = HttpClient.create()
            .tcpConfiguration(tcpClient -> tcpClient
                .proxy(proxy -> proxy
                    .type(ProxyProvider.Proxy.HTTP)
                    .host("ourproxy.com")
                    .port(8080)));

ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);

WebClient webClient = WebClient.builder()
        .clientConnector(connector)
        .baseUrl("https://targetsite.com")
        .build();

webClient.post()
    .uri("/service/serviceName")
    .body(BodyInserters.fromObject(reqData))
    .retrieve()
    .bodyToMono(WebServiceResponse.class)

但如果我使用System.setProperty("http.proxyHost","ourproxy.com"); 设置相同的代理详细信息 System.setProperty("http.proxyPort","8080"); 要么 JVM 运行时参数-Dhttp.proxyHost=ourproxy.com -Dhttp.proxyPort=8080

WebClient webClient = WebClient.builder()
        .baseUrl("https://targetsite.com")
        .build();

System.setProperty("http.proxyHost", "ourproxy.com");
System.setProperty("http.proxyPort", "8080");

webClient.post()
    .uri("/service/serviceName")
    .body(BodyInserters.fromObject(reqData))
    .retrieve()
    .bodyToMono(WebServiceResponse.class)

调用因 UnknownHostException 失败,例如,

[04/11/2019 12:32:43.031 IST] DEBUG [reactor-http-epoll-3] [PooledConnectionProvider:254] - Creating new client pool [http] for targetsite.com:443
[04/11/2019 12:32:43.033 IST] DEBUG [reactor-http-epoll-3] [PooledConnectionProvider:254] - [id: 0xe4a0dc15] Created new pooled channel, now 0 active connections and 1 inactive connections
[04/11/2019 12:32:43.045 IST] DEBUG [reactor-http-epoll-3] [SslProvider:254] - [id: 0xe4a0dc15] SSL enabled using engine SSLEngineImpl and SNI targetsite.com:443
[04/11/2019 12:32:43.046 IST] DEBUG [reactor-http-epoll-3] [BootstrapHandlers:254] - [id: 0xe4a0dc15] Initialized pipeline DefaultChannelPipeline{(reactor.left.sslHandler = io.netty.handler.ssl.SslHandler), (reactor.left.sslReader = reactor.netty.tcp.SslProvider$SslReadHandler), (BootstrapHandlers$BootstrapInitializerHandler#0 = reactor.netty.channel.BootstrapHandlers$BootstrapInitializerHandler), (SimpleChannelPool$1#0 = io.netty.channel.pool.SimpleChannelPool$1), (reactor.left.httpCodec = io.netty.handler.codec.http.HttpClientCodec), (reactor.left.decompressor = io.netty.handler.codec.http.HttpContentDecompressor), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
[04/11/2019 12:32:43.165 IST] ERROR [reactor-http-epoll-2] [AbstractErrorWebExceptionHandler:117] - [13ebf1eb] 500 Server Error for HTTP POST "/service/serviceName"
java.net.UnknownHostException: targetsite.com: Name or service not known

请帮忙,如果我通过 JVM 运行时参数或系统属性设置代理详细信息,为什么我的代码无法运行。

其实我想避免代码级代理设置。所以请指导我更正我的代码或方法,以便我可以使用 JVM 运行时参数选项。

【问题讨论】:

    标签: spring-boot spring-webclient


    【解决方案1】:

    后来当我向reactor-netty 团队(https://github.com/reactor/reactor-netty/issues/887#issuecomment-549439355) 提出这个问题时,他们确认reactor.netty.http.client.HttpClient 不支持系统属性。唯一的选择是通过 tcpConfiguration 进行设置,我已经在我的问题中提到过;所以我用这句话来结束这个问题。

    谢谢大家

    【讨论】:

    • 如果 httpClient 是在黑盒库中创建的呢?
    【解决方案2】:

    您需要在创建 HttpClient 实例时设置代理主机和端口。

    HttpClient httpClient =
                HttpClient.create()
                        .proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
                                .host(sasConfig.getProxyHost())
                                .port(Integer.parseInt(sasConfig.getProxyPort())));
    
    ReactorClientHttpConnector conn = new ReactorClientHttpConnector(httpClient);
    
    WebClient webClient = WebClient.builder().clientConnector(conn).build();
    

    【讨论】:

    • 我也在使用相同的代码,但是在运行代码时,我遇到了一个不一致的错误:无法写入 TLS 控制帧。我不明白这个错误是如何产生的。您能否阐明导致此错误的原因以及如何避免此错误?
    【解决方案3】:

    问题是HttpClient 默认情况下不会使用 Java VM 代理设置。你需要明确地让它使用它们。所以尝试以下方法;

    HttpClient httpClient = HttpClient.create()
                .useSystemProperties();
    

    并使用 HttpClient 创建 WebClient 以编程方式或使用 VM Args 设置 JVM 的代理设置。

    System.setProperty("http.proxyHost","ourproxy.com"); 
    System.setProperty("http.proxyPort","8080"); 
    
    -Dhttp.proxyHost=ourproxy.com -Dhttp.proxyPort=8080
    

    【讨论】:

    • 感谢@shazin,但我无法在 HttpClient 类中看到 useSystemProperties()。我正在使用 reactor.netty.http.client.HttpClient。但我可以通过 Apache HttpClient 看到这个 useSystemProperties() 属性。这个 Apache HttpClient 是否也像 netty 一样响应式支持?
    • 嗨@shazin,后来当我向reactor-netty 团队(github.com/reactor/reactor-netty/issues/…) 提出这个问题时,他们确认reactor.netty.http.client 不支持系统属性。 Http客户端。唯一的选择是通过我在问题中提到的 tcpConfiguration 进行设置;所以再次感谢你,我用这句话来结束这个问题。
    猜你喜欢
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    相关资源
    最近更新 更多