LoginSignup
2
4

More than 3 years have passed since last update.

Spring RestTemplateでAPI呼び出し時のプロキシとタイムアウト設定

Last updated at Posted at 2019-07-13

RestTempleteを使って外部APIを呼び出すために、プロキシ経由で接続する必要がありましたので、調べました。

追記
GETメソッドでボディを送ることができない問題に対する対処方法を追加しました。

バージョン
SpringBoot 2.1.6.RELEASE
HttpClient 4.5.9

RestTemplateの設定を行うRestTemplateCustomizerインターフェース

customizeメソッドに設定処理を実装します。

プロキシの設定

HttpClientBuilderにプロキシホスト(ホスト、ポート番号)を設定します。
認証(ユーザ名、パスワード)が必要な場合には、CredentialProviderに認証情報をセットしてHttpClientBuilderにセットします。

タイムアウトの設定

タイムアウトの設定は、HttpComponentsClientHttpRequestFactoryにセットします。

クラス全体のコード

RestTemplateConfig.java
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class RestTemplateConfig implements RestTemplateCustomizer {

    @Value("${proxy.host:#{null}}")
    private String proxyHost;

    @Value("${proxy.port:0}")
    private int proxyPort;

    @Value("${proxy.user:#{null}}")
    private String proxyUser;

    @Value("${proxy.password:#{null}}")
    private String proxyPassword;

    @Value("${api.connect.timeout:0}")
    private int connectTimeout;

    @Value("${api.read.timeout:0}")
    private int readTimeout;

    @Override
    public void customize(RestTemplate restTemplate) {

        HttpClientBuilder builder;
        if (proxyHost != null && !proxyHost.isEmpty() && proxyPort != 0) {
            builder = HttpClientBuilder.create().setProxy(new HttpHost(proxyHost, proxyPort));
            if (proxyUser != null && !proxyUser.isEmpty() && proxyPassword != null && !proxyPassword.isEmpty()) {
                AuthScope authScope = new AuthScope(proxyHost, proxyPort);
                UsernamePasswordCredentials usernamePassword = new UsernamePasswordCredentials(proxyUser, proxyPassword);
                BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
                credentialsProvider.setCredentials(authScope, usernamePassword);
                builder.setDefaultCredentialsProvider(credentialsProvider);
            }
        }
        else {
            builder = HttpClientBuilder.create();
        }

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(builder.build());
        if (connectTimeout > 0) {
            requestFactory.setConnectTimeout(connectTimeout);
        }
        if (readTimeout > 0) {
            requestFactory.setReadTimeout(readTimeout);
        }

        restTemplate.setRequestFactory(requestFactory);
    };
}

GETメソッドでボディを送れるようにする

デフォルトのままだと、GETメソッドでリクエストボディを送ることができない。HttpComponentsClientHttpRequestFactoryを拡張してGETメソッドでリクエストボディを送れるようになった。

参照
Making a GET request with request body using Spring RestTemplate

        class HttpEntityEnclosingRequest extends HttpEntityEnclosingRequestBase {
            HttpEntityEnclosingRequest(URI uri) {
                setURI(uri);
            }
            @Override
            public String getMethod() {
                return HttpMethod.GET.name();
            }
        }

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(builder.build()) {
            @Override
            protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
                if (httpMethod == HttpMethod.GET) {
                    return new HttpEntityEnclosingRequest(uri);
                }
                return super.createHttpUriRequest(httpMethod, uri);
            }
        };
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4