ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Feign 다이나믹하게 proxy 사용하기
    Java 2022. 4. 13. 09:50
    반응형

    개발을 하다보면 naver.com은 proxy server를 통하고 싶고 google.com은 proxy server를 통하고 싶지 않을 때가 있다. 그러나 보통 System Property로 proxy를 설정하면 전역적으로 proxy가 적용된다. 따라서 다이나믹하게 proxy를 적용할 수 있는 방법을 연구했고 기록을 남긴다.

     

    System Property 사용하기

    https://11st-tech.github.io/2021/09/07/proxy-setting-guide/

     

    Java proxy setting guide | 11번가 TechBlog — 11번가 기술블로그

    안녕하세요. 11번가 Platform Engineering 팀의 서버 개발자 김보배 입니다. 서버 구성에서 보안적인 이유 등으로 Proxy 서버를 중간에 두고 허용된 요청만을 처리하도록 하는 경우가 많습니다. 그런 경

    11st-tech.github.io

     

    Feign 동적 proxy 적용

    위 게시글에 내용 설명은 자세히 나와있고 내가 적용한 방법을 공유한다.

    build.gradle

    implementation 'io.github.openfeign:feign-httpclient:10.10.1'

     

    build.gradle에 io.github.openfeign을 추가하지 않으면 DefaultRoutePlanner를 사용하지 않는다.

     

    application.yml

    #예시
    proxy:
      url: http://proxy.com:1234
      hosts: 'naver.com', 'hanseokhyeon.tistory.com'

     

    application.yml에 proxy를 통해 접근할 url을 proxy.hosts에 지정한다.

     

    CustomProxyRoutePlanner.java

    import org.apache.http.HttpException;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpRequest;
    import org.apache.http.annotation.Contract;
    import org.apache.http.annotation.ThreadingBehavior;
    import org.apache.http.conn.SchemePortResolver;
    import org.apache.http.impl.conn.DefaultRoutePlanner;
    import org.apache.http.protocol.HttpContext;
    import org.apache.http.util.Args;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.stream.Collectors;
    
    @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
    public class CustomProxyRoutePlanner extends DefaultRoutePlanner {
    
        private final HttpHost proxy;
        private final List<HttpHost> proxyHttpHost;
    
        public CustomProxyRoutePlanner(final HttpHost proxy, final SchemePortResolver schemePortResolver, final List<String> proxyURIs) {
            super(schemePortResolver);
            this.proxy = Args.notNull(proxy, "Proxy host");
            this.proxyHttpHost = proxyURIs.stream()
                    .map(HttpHost::new)
                    .collect(Collectors.toList());
        }
    
        public CustomProxyRoutePlanner(final HttpHost proxy) {
            this(proxy, null, Collections.emptyList());
        }
    
        public CustomProxyRoutePlanner(final HttpHost proxy, final List<String> proxyURIs) {
            this(proxy, null, proxyURIs);
        }
    
        @Override
        protected HttpHost determineProxy(
                final HttpHost target,
                final HttpRequest request,
                final HttpContext context) throws HttpException {
    
            for (HttpHost httpHost : proxyHttpHost) {
                if (target.getHostName().equals(httpHost.getHostName())) {
                    return proxy;
                }
            }
            return null;
        }
    
    }

     

    determineProxy 메서드에서 proxy를 통할지 말지 결정한다. 생성자에서 만들어둔 HttpHost 리스트에 같은 hostname을 가진 인스턴스가 있으면 proxy를 return하고 없으면 null을 리턴한다. naver.com은 리스트에 존재하므로 proxy를 return하고 proxy를 통해 접근된다.

     

    CustomHttpClientConfiguration.java

    import org.apache.http.HttpHost;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.List;
    
    @Configuration
    public class CustomHttpClientConfiguration {
    
        @Value("${proxy.url}")
        private String proxyUrl;
    
        @Value("${proxy.hosts}")
        private List<String> proxyHosts;
    
        @Bean
        public HttpClientBuilder apacheHttpClientBuilder() throws MalformedURLException {
            var proxy = new HttpHost(new URL(proxyUrl).getHost(), new URL(proxyUrl).getPort());
            var customRoutePlanner = new CustomProxyRoutePlanner(proxy, proxyHosts);
            return HttpClientBuilder.create().setRoutePlanner(customRoutePlanner);
        }
    }

     

    위에서 작성한 CustomProxyRoutePlanner을 사용할 수 있도록 Builder를 선언하고 Bean으로 등록한다.

    반응형

    'Java' 카테고리의 다른 글

    엑셀 업로드 에러  (0) 2023.01.10
    ES Json 쿼리 조회  (0) 2022.12.15
    Feign 다이나믹 header  (0) 2022.04.12
    Feign POST 파일 전송 (multipart/form-data)  (0) 2022.04.12
    Feign POST application/x-www-form-urlencoded  (0) 2022.04.12
Designed by Tistory.