FeignのProxy対応(認証あり)

インターネットに接続する際、認証が必要なproxyを経由しなければならない会社等もあるかと思います。
そのような環境でAPIクライアントであるFeignを利用して、インターネット上に公開されているAPIを呼び出す際のproxyの設定方法について説明したいと思います。

FeignはHTTPリクエストを発行する処理を別のライブラリにデリゲートしています。
つまり、利用するライブラリのproxy対応を行えばよいということです。

今回はFeignGitHubページで説明されているGitHubの指定したリポジトリのコントリビュータを取得するサンプルproxy対応に変更してみます。

なお、Feignの説明ついては「インターフェースだけでAPIクライアントを実装するFeignがすごく便利!」に書いていますのでそちらを参照ください。

GitHubDemo.java
package com.example.feign.demo.github;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.concurrent.TimeUnit;

import feign.Feign;
import feign.jackson.JacksonDecoder;
import okhttp3.Authenticator;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;

/**
 * modify Feign example(https://github.com/OpenFeign/feign) to corresponded proxy
 */
public class GitHubDemo {

    public static void main(String[] args) {

        // create instance of okhttp3.OkHttpClient corresponded proxy 
        OkHttpClient client = createOkHttpClientCorrespondedProxy("127.0.0.1",
                8080, "userId", "pass");

        // feign use proxy with authentication
        GitHub github = Feign.builder()
                // set instance of feign.Client.OkHttpClient
                .client(new feign.okhttp.OkHttpClient(client))
                // use Jackson
                .decoder(new JacksonDecoder())
                .target(GitHub.class, "https://api.github.com");

        // call api [GET /repos/{owner}/{repo}/contributors]
        List<Contributor> contributors = github.contributors("OpenFeign",
                "feign");
        for (Contributor contributor : contributors) {
            System.out.println(
                    contributor.login + " (" + contributor.contributions + ")");
        }
    }

    /**
     * create instance of okhttp3.OkHttpClient corresponded proxy
     * @param proxyHost proxy's host url or ipAddress
     * @param proxyPort proxy's port number
     * @param userId userId of proxy's authentication
     * @param pass pass of proxy's authentication
     * @return instance of okhttp3.OkHttpClient
     */
    private static OkHttpClient createOkHttpClientCorrespondedProxy(
            String proxyHost, int proxyPort, String userId, String pass) {

        // okhttp3.Authenticator : correct
        // java.net.Authenticator : incorrect
        Authenticator proxyAuthenticator = new Authenticator() {
            @Override
            public Request authenticate(Route route,
                    Response response) throws IOException {
                String credential = Credentials.basic(userId, pass);
                return response.request().newBuilder()
                        .header("Proxy-Authorization", credential).build();
            }
        };

        // okhttp3.OkHttpClient : correct
        // feign.Client.OkHttpClient : incorrect
        return new OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .proxy(new Proxy(Proxy.Type.HTTP,
                        new InetSocketAddress(proxyHost, proxyPort)))
                .proxyAuthenticator(proxyAuthenticator).build();
    }
}

注意すべきポイントを以下に示します。

  • feign.okhttp.OkHttpClientのインスタンスを生成する際、okhttp3.OkHttpClientを引数にとるコンストラクタを利用する
  • okhttp3.OkHttpClientのインスタンスを生成する際、proxyに対応するようにコンフィグレーションする
  • 同じクラス名のものがあるのでimportする際は注意すること
    • okhttp3.Authenticatorが正しく、java.net.Authenticatorは誤り
    • okhttp3.OkHttpClientが正しく、feign.Client.OkHttpClientは誤り(proxy対応のokhttpのインスタンスを生成する)

(参考)
https://stackoverflow.com/questions/35554380/okhttpclient-proxy-authentication-how-to

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.