programing

Spring Web Client에서 프록시 설정이 작동하지 않음

newstyles 2023. 6. 23. 21:48

Spring Web Client에서 프록시 설정이 작동하지 않음

다음 WebClient는 인터넷 연결에서는 잘 작동하지만 프록시 연결에서는 작동하지 않습니다.

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 런타임 인수 옵션을 사용할 수 있도록 코드 또는 접근 방식을 수정하도록 안내해 주십시오.

나중에 제가 reactor-netty 팀(https://github.com/reactor/reactor-netty/issues/887#issuecomment-549439355), 에 이 문제를 제기했을 때, 그들에 의해 시스템 특성이 reactor에 의해 지원되지 않는다는 것이 확인되었습니다.netty.sys.client.HttpClient.유일한 옵션은 이미 제 질문에서 언급한 tcpConfiguration을 통해 설정하는 것입니다. 그래서 저는 이 질문을 이 발언으로 마무리합니다.

모두에게 감사를 표합니다.

아래에 따라 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();

저는 다른 답변에 대해 언급할 충분한 평판이 없기 때문에 여기서 제 답변을 시작해야 합니다.

reactor-netty v1.0.8 이후에는 시스템 속성에서 프록시를 구성할 수 있습니다.

예:

WebClient
    .builder()
    .clientConnector(
        new ReactorClientHttpConnector(
            HttpClient.create().proxyWithSystemProperties()))
.build()

저는 비슷한 상황을 겪었고 결국 어리석은 실수가 무엇인지 찾기 위해 고군분투했습니다.

  1. 도청을 활성화했습니다.
     val httpClient = HttpClient.create()
                    .wiretap(
                        MyClient::class.java.toString(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL)
    
                webClient=WebClient.builder()
                    .clientConnector(ReactorClientHttpConnector(httpClient))
                    .codecs(consumerCodecForIncreasedPayloadSize)
                    .build()
  1. 그리고 나서 저는 통나무에서 이상한 것을 발견할 수 있었습니다.
    [21119d8d] CONNECT: http://myProxy.my.company.com/<unresolved>:8080

그게 뭐였더라<unresolved>프록시에 CONNECT 명령을 내릴 때 어떤 것이 있습니까?

  1. 그때 나는 마침내 깨달았다:https.proxyHost시작할 때 설정한 값이 다음 값이 아니어야 합니다.http://myProxy.my.company.com간단히 말하면myProxy.my.company.com을 제외하고http://

효과가 있었습니다.

이것이 저에게 효과가 있었던 것입니다.

1단계: 프록시 환경 변수 정의

-Dhttp.proxyHost=<proxyHost>
-Dhttp.proxyPort=8080
-Dhttps.proxyHost=<proxyHost>
-Dhttps.proxyPort=8080
-Dhttps.nonProxyHosts=localhost
  1. webClient에서 프록시 구성

    @Configuration
    public class WebClientConfiguration {    
     @Bean
     public WebClient webClient() {
         return WebClient.builder() //
                 .defaultHeader(ACCEPT, APPLICATION_JSON_VALUE) //
                 .clientConnector(new ReactorClientHttpConnector(httpClient())) //
                 .build();
     }
    
     private HttpClient httpClient() {
         return HttpClient //
                 .create() //
                 .proxyWithSystemProperties();
     }
    

    }

  2. Spring Cloud Proxy 속성 설정(애플리케이션 시작 시)

    static {
       String nonProxyHosts = System.getProperty("http.nonProxyHosts");
       if (nonProxyHosts != null) {
         String regexProxyList = nonProxyHosts.replaceAll("\\.", "\\\\.").replaceAll("\\/", "\\\\/").replaceAll("\\*", ".\\*");
         System.setProperty("spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern", regexProxyList);
     }
     String proxyHost = System.getProperty("https.proxyHost");
     String proxyPort = System.getProperty("https.proxyPort");
     if (proxyHost != null && proxyPort != null) {
         System.setProperty("spring.cloud.gateway.httpclient.proxy.host", proxyHost);
         System.setProperty("spring.cloud.gateway.httpclient.proxy.port", proxyPort);
     }
    }
    

언급URL : https://stackoverflow.com/questions/58689235/proxy-setting-not-working-with-spring-webclient