The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

REST クライアントの利用

このガイドでは、REST APIと対話するためのREST Clientの使用方法について説明します。 RESTクライアントは、Quarkus REST(旧RESTEasy Reactive)と互換性のあるRESTクライアントの実装です。

アプリケーションでクライアントを使用し、RESTエンドポイントを公開する場合は、サーバー部分に Quarkus REST を使用してください。

要件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 17+がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.9.9

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

ソリューション

次の章で紹介する手順に沿って、ステップを踏んでアプリケーションを作成することを推奨します。 ただし、完成した例にそのまま進むこともできます。

git clone https://github.com/quarkusio/quarkus-quickstarts.git で Git リポジトリーをクローンします。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードします。

解決策は rest-client-quickstart ディレクトリー にあります。

Maven プロジェクトの作成

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。

コマンドラインインタフェース
quarkus create app org.acme:rest-client-quickstart \
    --extension='rest-jackson,rest-client-jackson' \
    --no-code
cd rest-client-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.21.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=rest-client-quickstart \
    -Dextensions='rest-jackson,rest-client-jackson' \
    -DnoCode
cd rest-client-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=rest-client-quickstart"

このコマンドは、REST エンドポイントを持つ Maven プロジェクトを生成し、 rest-clientresteasy-jackson のエクステンションをインポートします。

  • REST サーバーのサポートには、 rest-jackson エクステンションを使用してください。Jackson を使用したくない場合は、代わりに rest を使用してください;

  • REST クライアントのサポートには rest-client-jackson エクステンションを使用してください。Jackson を使用したくない場合は、代わりに rest-client を使用してください。

Quarkus プロジェクトがすでに設定されている場合は、プロジェクトのベースディレクトリーで次のコマンドを実行することで、 rest-client-jackson エクステンションをプロジェクトに追加できます。

コマンドラインインタフェース
quarkus extension add rest-client-jackson
Maven
./mvnw quarkus:add-extension -Dextensions='rest-client-jackson'
Gradle
./gradlew addExtension --extensions='rest-client-jackson'

これにより、ビルドファイルに次の内容が追加されます。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-rest-client-jackson")

モデルのセットアップ

このガイドでは、stage.code.quarkus.io サービスが提供する REST API の一部を利用する方法をデモします。 まず最初に、使用するモデルを Extension POJO の形式でセットアップします。

src/main/java/org/acme/rest/client/Extension.java ファイルを作成し、以下の内容を設定します。

package org.acme.rest.client;

import java.util.List;

public class Extension {

    public String id;
    public String name;
    public String shortName;
    public List<String> keywords;

}

上記のモデルは、サービスによって提供されるフィールドのサブセットに過ぎませんが、このガイドの目的には十分です。

インターフェイスの作成

REST Client の使用は、適切な Jakarta REST および MicroProfile アノテーションを使用してインターフェイスを作成するのと同じくらい簡単です。今回の場合、インターフェイスは src/main/java/org/acme/rest/client/ExtensionsService.java で作成し、以下の内容を持つ必要があります。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);
}

getById メソッドは、私たちのコードに、Code Quarkus API からidを指定してエクステンションを問い合わせる機能を与えます。クライアントがすべてのネットワーキングとマーシャリングを処理してくれるので、このような技術的な詳細は一切ありません。

上のコードのアノテーションの目的は以下の通りです。

  • @RegisterRestClient により、Quarkus は、このインターフェイスが REST Client として CDI 注入に利用可能である ことを知ることができます。

  • @Path@GET@QueryParam は、サービスへのアクセス方法を定義するために使用される標準的な Jakarta REST アノテーションです。

quarkus-rest-client-jackson エクステンションがインストールされている場合、メディア型が @Produces または @Consumes アノテーションによって明示的に設定されていない限り、Quarkus はほとんどの返り値に対してデフォルトで application/json メディア型を使用します。

JSONのデフォルトに依存しない場合は、エンドポイントに @Produces@Consumes のアノテーションを付けて、期待される content-types を正確に定義することが強く推奨されています。 これにより、ネイティブ実行可能ファイルに含まれる Jakarta REST プロバイダー (コンバーターと見なすことができます) の数を減らすことができます。

上記の getById メソッドはブロッキング呼び出しです。イベントループで呼び出さないでください。 非同期サポート セクションでは、ノンブロッキング呼び出しを行う方法について説明しています。

クエリーパラメーター

クエリーパラメーターを指定する最も簡単な方法は、クライアントメソッドのパラメーターに @QueryParam または @RestQuery というアノテーションを付けることです。 @RestQuery@QueryParam と同等ですが、名前を省略することができます。さらに、クエリーパラメーターを Map として 渡すこともでき、事前にパラメーターがわからない場合に便利です。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.RestQuery;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.Map;
import java.util.Set;
import java util.Optional;

@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);

    @GET
    Set<Extension> getByName(@RestQuery String name); (1)

    @GET
    Set<Extension> getByOptionalName(@RestQuery Optional<String> name);

    @GET
    Set<Extension> getByFilter(@RestQuery Map<String, String> filter); (2)

    @GET
    Set<Extension> getByFilters(@RestQuery MultivaluedMap<String, String> filters); (3)

}
1 リクエストクエリーには name をキーとするパラメーターが含まれます
2 Map エントリは、ちょうど 1 つのクエリーパラメーターを表します
3 MultivaluedMap は配列の値を送信することができます

@ClientQueryParam を使用

リクエストにクエリーパラメーターを追加するもうひとつの方法は、REST クライアントインターフェイスあるいはそのインターフェイスの特定のメソッドに @io.quarkus.rest.client.reactive.ClientQueryParam を使用することです。 アノテーションではクエリーパラメーター名を指定し、値は定数や設定プロパティー、あるいはメソッドの起動時に決定できます。

次の例では、さまざまな使い方を紹介します:

@ClientQueryParam(name = "my-param", value = "${my.property-value}") (1)
public interface Client {
    @GET
    String getWithParam();

    @GET
    @ClientQueryParam(name = "some-other-param", value = "other") (2)
    String getWithOtherParam();

    @GET
    @ClientQueryParam(name = "param-from-method", value = "{with-param}") (3)
    String getFromMethod();

    default String withParam(String name) {
        if ("param-from-method".equals(name)) {
            return "test";
        }
        throw new IllegalArgumentException();
    }
}
1 @ClientQueryParam をインターフェイスに配置することで、クライアントのすべてのリクエストに my-param が追加されるようにします。 ${…​} 構文を使用したため、パラメーターの実際の値は my.property-value 設定プロパティを使用して取得されます。
2 getWithOtherParam を呼び出すと、クエリーパラメーター my-param に加え、 some-other-paramother の値が追加されます。
3 getFromMethod を呼び出すと、 my-param のクエリーパラメーターに加えて、 param-from-methodtest の値 ( withParam のメソッドが param-from-method と呼び出されたときに返すため) が追加されます。

インターフェイスメソッドに @QueryParam のアノテーションが付いた引数がある場合、 その引数は @ClientQueryParam のアノテーションで指定されたものよりも優先されることに注意してください。

このアノテーションの詳細は、@ClientQueryParam の javadoc で確認できます。

フォームパラメーター

フォームパラメーターは、 @RestForm (または @FormParam) アノテーションを使用して指定できます。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.RestForm;

import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.Map;
import java.util.Set;

@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
public interface ExtensionsService {

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    Set<Extension> postId(@FormParam("id") String id);

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    Set<Extension> postName(@RestForm String name);

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    Set<Extension> postFilter(@RestForm Map<String, String> filter);

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    Set<Extension> postFilters(@RestForm MultivaluedMap<String, String> filters);

}

@ClientFormParamの使用

フォームパラメーターは、 @ClientQueryParam と同様に @ClientFormParam を使用して指定することもできます:

@ClientFormParam(name = "my-param", value = "${my.property-value}")
public interface Client {
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    String postWithParam();

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @ClientFormParam(name = "some-other-param", value = "other")
    String postWithOtherParam();

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @ClientFormParam(name = "param-from-method", value = "{with-param}")
    String postFromMethod();

    default String withParam(String name) {
        if ("param-from-method".equals(name)) {
            return "test";
        }
        throw new IllegalArgumentException();
    }
}

このアノテーションの詳細は @ClientFormParam のjavadocで確認できます。

パスパラメーター

GET リクエストにパスパラメーターが必要な場合は、 @QueryParam の代わりに (あるいは加えて) @PathParam ("parameter-name") アノテーションを使用することができます。 パスパラメーターとクエリーパラメーターは、必要に応じて以下の例のように組み合わせることができます。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import java.util.Set;

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    @Path("/stream/{stream}")
    Set<Extension> getByStream(@PathParam("stream") String stream, @QueryParam("id") String id);
}

動的ベース URL

REST クライアントでは、 io.quarkus.rest.client.reactive.Url アノテーションを使用して、呼び出しごとにベース URL をオーバーライドできます。

簡単な例を挙げてみます。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import java.util.Set;

import io.quarkus.rest.client.reactive.Url;

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    @Path("/stream/{stream}")
    Set<Extension> getByStream(@Url String url, @PathParam("stream") String stream, @QueryParam("id") String id);
}

url パラメーターが null 以外の場合、クライアントに設定されているベース URL がオーバーライドされます (デフォルトのベース URL 設定は引き続き必須です)。

大きなペイロードの送信

REST Client は、以下のいずれかの型を使用する場合、メモリー内にコンテンツをバッファーリングすることなく、任意の大きさの HTTP 本文を送信できます。

  • InputStream

  • Multi<io.vertx.mutiny.core.buffer.Buffer>

さらに、次のいずれかの型を使用すると、クライアントは任意の大きさのファイルを送信することもできます。

  • File

  • Path

その他のレスポンスプロパティーの取得

RestResponseの使用

HTTP レスポンスのボディだけでなく、ステータスコードやヘッダーなどの他のプロパティーも取得する必要がある場合は、 メソッドから org.jboss.resteasy.reactive.RestResponse を返すことができます。 以下に例を示します。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.jboss.resteasy.reactive.RestQuery;
import org.jboss.resteasy.reactive.RestResponse;

import java.util.Set;

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    RestResponse<Set<Extension>> getByIdResponseProperties(@RestQuery String id);
}
また、Jakarta REST型 Response を使用することもできますが、 エンティティーに対して強い型付けはされていません。

Jakarta RESTリソースの作成

src/main/java/org/acme/rest/client/ExtensionsResource.java ファイルを以下の内容で作成してください:

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.util.Set;

@Path("/extension")
public class ExtensionsResource {

    @RestClient (1)
    ExtensionsService extensionsService;


    @GET
    @Path("/id/{id}")
    public Set<Extension> id(String id) {
        return extensionsService.getById(id);
    }

    @GET
    @Path("/properties")
    public RestResponse<Set<Extension>> responseProperties(@RestQuery String id) {
        RestResponse<Set<Extension>> clientResponse = extensionsService.getByIdResponseProperties(id); (2)
        String contentType = clientResponse.getHeaderString("Content-Type");
        int status = clientResponse.getStatus();
        String setCookie = clientResponse.getHeaderString("Set-Cookie");
        Date lastModified = clientResponse.getLastModified();

        Log.infof("content-Type: %s status: %s Last-Modified: %s Set-Cookie: %s", contentType, status, lastModified,
                setCookie);

        return RestResponse.fromResponse(clientResponse);
    }
}

このリストには 2 つの興味深い部分があります。

1 クライアントスタブには、通常の CDI @Inject ではなく、 @RestClient アノテーションが挿入されます。
2 org.jboss.resteasy.reactive.RestResponse は、RestClient から RestResponse を介してレスポンスプロパティーを直接取得する効果的な方法として使用されます。 詳細は [Using RestResponse] を参照してください。

構成の作成

REST 呼び出しが行われるベース URL を決定するために、REST Client は application.properties からの設定を使用します。 プロパティーの名前は、以下のコードで表示される特定の規則に従う必要があります。

# Your configuration properties
quarkus.rest-client."org.acme.rest.client.ExtensionsService".url=https://stage.code.quarkus.io/api # (1)
1 この設定を行うと、 org.acme.rest.client.ExtensionsService を使用して実行されるすべてのリクエストは、ベース URL として https://stage.code.quarkus.io/api を使用することを意味します。 上記の設定を使用すると、 ExtensionsServicegetById メソッドを io.quarkus:quarkus-rest-client という値で呼び出すと、 https://stage.code.quarkus.io/api/extensions?id=io.quarkus:quarkus-rest-client に HTTP GET リクエストが行われることになります。

org.acme.rest.client.ExtensionsService は、前のセクションで作成した`ExtensionsService` インターフェイスの完全修飾名と 一致しなければならない ことに注意してください。

設定を容易にするために、 @RegisterRestClient configKey プロパティーを使用して、インターフェイスの完全修飾名とは別の設定ルートを使用することができます。

@RegisterRestClient(configKey="extensions-api")
public interface ExtensionsService {
    [...]
}
# Your configuration properties
quarkus.rest-client.extensions-api.url=https://stage.code.quarkus.io/api
quarkus.rest-client.extensions-api.scope=jakarta.inject.Singleton

クライアントのベース URL の設定は 必須 ですが、REST Client は @io.quarkus.rest.client.reactive.Url アノテーションを使用して、呼び出しごとにベース URL をオーバーライドすることをサポートしています。

すべての証明書を信頼し、SSL ホスト名検証を無効にする

このプロパティーセットは実稼働環境では使用しないでください。

特定の REST クライアントの TLS 接続を設定して、すべての証明書を信頼し、tls エクステンションを使用してホスト名の検証を無効にすることができます。 最初に、tls 設定バケットを設定する必要があります。

すべての証明書を信頼するには、次のように指定します。

quarkus.tls.tls-disabled.trust-all=true

SSL ホスト名検証を無効にするには、次のように指定します。

quarkus.tls.tls-disabled.hostname-verification-algorithm=NONE

最後に、適切な tls 設定名を使用して REST クライアントを設定します。

quarkus.rest-client.extensions-api.tls-configuration-name=tls-disabled

HTTP/2 サポート

REST Clientでは、HTTP/2はデフォルトで無効になっています。有効にしたい場合は、次のように設定することができます:

// for all REST Clients:
quarkus.rest-client.http2=true
// or for a single REST Client:
quarkus.rest-client.extensions-api.http2=true

または、Application-Layer Protocol Negotiation (alpn) TLSエクステンションを有効にすると、クライアントは、サーバーが互換性のあるものよりも、どのHTTPバージョンを使用するかをネゴシエートすることができます。デフォルトでは、まずHTTP/2を使用しようとし、有効になっていない場合はHTTP/1.1を使用します。有効にしたい場合は、以下のように設定します:

quarkus.rest-client.alpn=true
// or for a single REST Client:
quarkus.rest-client.extensions-api.alpn=true

QuarkusRestClientBuilderを使用したプログラムによるクライアントの作成

クライアントに @RegisterRestClient アノテーションを付け、クライアントを @RestClient で注入する代わりに、 プログラムで REST Client を作成することもできます。 これは RestClientBuilder で行います。

このアプローチでは、クライアントインターフェイスは次のようになります。

package org.acme.rest.client;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;

@Path("/extensions")
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);
}

そして、次のようなサービス:

package org.acme.rest.client;

import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.net.URI;
import java.util.Set;

@Path("/extension")
public class ExtensionsResource {

    private final ExtensionsService extensionsService;

    public ExtensionsResource() {
        extensionsService = QuarkusRestClientBuilder.newBuilder()
            .baseUri(URI.create("https://stage.code.quarkus.io/api"))
            .build(ExtensionsService.class);
    }

    @GET
    @Path("/id/{id}")
    public Set<Extension> id(String id) {
        return extensionsService.getById(id);
    }
}

QuarkusRestClientBuilder インターフェイスは、追加の設定オプションを使用してクライアントをプログラムで作成するための Quarkus 固有の API です。これ以外にも、Microprofile API の RestClientBuilder インターフェイスを使用することもできます。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.RestClientBuilder;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.net.URI;
import java.util.Set;

@Path("/extension")
public class ExtensionsResource {

    private final ExtensionsService extensionsService;

    public ExtensionsResource() {
        extensionsService = RestClientBuilder.newBuilder()
            .baseUri(URI.create("https://stage.code.quarkus.io/api"))
            .build(ExtensionsService.class);
    }

    // ...
}

カスタムHTTPオプションの使用

REST Client は、内部的に Vert.x HTTP Client を使用して、ネットワーク接続をします。REST Client Reactive エクステンションでは、プロパティーを使っていくつかの設定を行うことができます。以下に例を示します。

  • quarkus.rest-client.client-prefix.connect-timeout で、接続タイムアウトをミリ秒単位で設定します。

  • `quarkus.rest-client.client-prefix.max-redirects`でリダイレクトの回数を制限できます。

しかし、Vert.x HTTP Client 内には、接続を設定するための多くのオプションがあります。 このリンク のVert.x HTTP Client Options API ですべてのオプションを参照してください。

REST Client が内部的に使用している Vert.x HTTP Client インスタンスを完全にカスタマイズするには、CDI 経由で、またはプログラムでクライアントを作成するときに、HTTP Client Options インスタンスを提供します。

ここでは、CDIを使用してHTTPクライアントオプションを提供する方法について、例を挙げて説明します:

package org.acme.rest.client;

import jakarta.enterprise.inject.Produces;
import jakarta.ws.rs.ext.ContextResolver;

import io.vertx.core.http.HttpClientOptions;
import io.quarkus.arc.Unremovable;

@Provider
public class CustomHttpClientOptions implements ContextResolver<HttpClientOptions> {

    @Override
    public HttpClientOptions getContext(Class<?> aClass) {
        HttpClientOptions options = new HttpClientOptions();
        // ...
        return options;
    }
}

これで、すべてのRESTクライアントが、あなたのカスタムHTTPクライアントオプションを使用するようになります。

もう一つの方法は、コードを用いてでクライアントを作成する際に、カスタムHTTPクライアントオプションを提供することです。

package org.acme.rest.client;

import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.net.URI;
import java.util.Set;

import io.vertx.core.http.HttpClientOptions;

@Path("/extension")
public class ExtensionsResource {

    private final ExtensionsService extensionsService;

    public ExtensionsResource() {
        HttpClientOptions options = new HttpClientOptions();
        // ...

        extensionsService = QuarkusRestClientBuilder.newBuilder()
            .baseUri(URI.create("https://stage.code.quarkus.io/api"))
            .httpClientOptions(options) (1)
            .build(ExtensionsService.class);
    }

    // ...
}
1 クライアントはCDI経由で提供されたHTTPクライアントオプションよりも、登録されたHTTPクライアントオプションを使用します。

リダイレクト

HTTPサーバーは、ステータスコードが "3 "で始まるレスポンスと、リダイレクト先のURLを保持するHTTPヘッダー "Location" を送信することで、レスポンスを別の場所にリダイレクトできます。RESTクライアントがHTTPサーバーからリダイレクトレスポンスを受信しても、新しい場所への再リクエストを自動的に実行することはありません。"follow-redirects"プロパティを追加することで、REST Clientで自動リダイレクトを有効にすることができます:

  • quarkus.rest-client.follow-redirects で、すべての REST クライアントに対してリダイレクトが有効になります。

  • quarkus.rest-client.<client-prefix>.follow-redirects で、特定の REST クライアントに対してリダイレクトが有効になります。

このプロパティがtrueの場合、REST Clientは、HTTPサーバーからリダイレクトレスポンスを受信すると、新しいリクエストを実行します。

さらに、プロパティ "max-redirects" を使って、リダイレクトの回数を制限することができます。

重要な注意点として、 RFC2616 仕様によると、デフォルトではリダイレクトは GET または HEAD メソッドに対してのみ実行されます。しかし、REST Client では、 @ClientRedirectHandler アノテーションを使用するか、CDI を利用するか、またはクライアント作成時にプログラム的に設定することで、POST や PUT メソッドのリダイレクトを有効にしたり、より複雑なロジックに従ってリダイレクトを行うカスタムリダイレクトハンドラーを指定できます。

@ClientRedirectHandler アノテーションを使用して独自のカスタムリダイレクトハンドラーを登録する方法の例を見てみましょう。

import jakarta.ws.rs.core.Response;

import io.quarkus.rest.client.reactive.ClientRedirectHandler;

@RegisterRestClient(configKey="extensions-api")
public interface ExtensionsService {
    @ClientRedirectHandler
    static URI alwaysRedirect(Response response) {
        if (Response.Status.Family.familyOf(response.getStatus()) == Response.Status.Family.REDIRECTION) {
            return response.getLocation();
        }

        return null;
    }
}

"alwaysRedirect" リダイレクトハンドラーは、指定された REST Client (この例では "ExtensionsService" クライアント) によってのみ使用されます。

または、CDI 経由ですべての REST Client にカスタムリダイレクトハンドラーを提供することもできます。

import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.Provider;

import org.jboss.resteasy.reactive.client.handlers.RedirectHandler;

@Provider
public class AlwaysRedirectHandler implements ContextResolver<RedirectHandler> {

    @Override
    public RedirectHandler getContext(Class<?> aClass) {
        return response -> {
            if (Response.Status.Family.familyOf(response.getStatus()) == Response.Status.Family.REDIRECTION) {
                return response.getLocation();
            }
            // no redirect
            return null;
        };
    }
}

これで、すべての REST Client が、お客様のカスタムリダイレクトハンドラーを使用するようになります。

別の方法として、クライアントを作成するときにプログラムで提供する方法があります。

@Path("/extension")
public class ExtensionsResource {

    private final ExtensionsService extensionsService;

    public ExtensionsResource() {
        extensionsService = QuarkusRestClientBuilder.newBuilder()
            .baseUri(URI.create("https://stage.code.quarkus.io/api"))
            .register(AlwaysRedirectHandler.class) (1)
            .build(ExtensionsService.class);
    }

    // ...
}
1 クライアントは、CDI 経由で提供されたリダイレクトハンドラーよりも、登録されたリダイレクトハンドラーを使用します (存在する場合)。

テストの更新

次に、エンドポイントに加えられた変更を反映させるために、機能テストを更新する必要があります。 src/test/java/org/acme/rest/client/ExtensionsResourceTest.java ファイルを編集し、テストの内容を以下のように変更します。

package org.acme.rest.client;

import io.quarkus.test.junit.QuarkusTest;

import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.greaterThan;

@QuarkusTest
public class ExtensionsResourceTest {

    @Test
    public void testExtensionsIdEndpoint() {
        given()
            .when().get("/extension/id/io.quarkus:quarkus-rest-client")
            .then()
            .statusCode(200)
            .body("$.size()", is(1),
                "[0].id", is("io.quarkus:quarkus-rest-client"),
                "[0].name", is("REST Client"),
                "[0].keywords.size()", greaterThan(1),
                "[0].keywords", hasItem("rest-client"));
    }
}

上のコードでは、 REST Assuredjson-path 機能を使用しています。

非同期サポート

クライアントのリアクティブな性質を最大限に活用するには、REST Client エクステンションのノンブロッキングフレーバーを使用します。 このエクステンションは CompletionStageUni をサポートしています。 それでは、実際に ExtensionsService REST インターフェイスに getByIdAsync メソッドを追加して、この動きを見てみましょう。コードは以下のようになります。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;
import java.util.concurrent.CompletionStage;

@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);

    @GET
    CompletionStage<Set<Extension>> getByIdAsync(@QueryParam("id") String id);
}

src/main/java/org/acme/rest/client/ExtensionsResource.java ファイルを開き、以下の内容で更新してください。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.util.Set;
import java.util.concurrent.CompletionStage;

@Path("/extension")
public class ExtensionsResource {

    @RestClient
    ExtensionsService extensionsService;


    @GET
    @Path("/id/{id}")
    public Set<Extension> id(String id) {
        return extensionsService.getById(id);
    }

    @GET
    @Path("/id-async/{id}")
    public CompletionStage<Set<Extension>> idAsync(String id) {
        return extensionsService.getByIdAsync(id);
    }
}

呼び出しがノンブロッキングになったため、 idAsync メソッドがイベントループで呼び出されることに注意してください。 つまり、ワーカープールのスレッドにオフロードされないので、ハードウェアリソースの使用量を減らすことができます。 詳細は、Quarkus REST 実行モデル を参照してください。

非同期メソッドをテストするには、 ExtensionsResourceTest に以下のテストメソッドを追加します。

@Test
public void testExtensionIdAsyncEndpoint() {
    given()
        .when().get("/extension/id-async/io.quarkus:quarkus-rest-client")
        .then()
        .statusCode(200)
        .body("$.size()", is(1),
            "[0].id", is("io.quarkus:quarkus-rest-client"),
            "[0].name", is("REST Client"),
            "[0].keywords.size()", greaterThan(1),
            "[0].keywords", hasItem("rest-client"));
}

Uni 版は非常に似ています。

package org.acme.rest.client;

import io.smallrye.mutiny.Uni;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;

@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
public interface ExtensionsService {

    // ...

    @GET
    Uni<Set<Extension>> getByIdAsUni(@QueryParam("id") String id);
}

ExtensionsResource は次のようになります。

package org.acme.rest.client;

import io.smallrye.mutiny.Uni;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.util.Set;

@Path("/extension")
public class ExtensionsResource {

    @RestClient
    ExtensionsService extensionsService;


    // ...

    @GET
    @Path("/id-uni/{id}")
    public Uni<Set<Extension>> idUni(String id) {
        return extensionsService.getByIdAsUni(id);
    }
}
Mutiny

前のスニペットでは、Mutinyのリアクティブ型を使用していますが、 もし慣れていない場合は、まず Mutiny - 直感的なリアクティブプログラミングライブラリ を読んでください。

Uni を返すとき、すべての サブスクリプション は、リモートサービスを呼び出します。 つまり、 Uni で再購読してリクエストを再送信するか、以下のように retry を使用することができます。

@RestClient ExtensionsService extensionsService;

// ...

extensionsService.getByIdAsUni(id)
    .onFailure().retry().atMost(10);

CompletionStage を使用する場合は、再試行のためにサービスのメソッドを呼び出す必要があります。 この違いは、Mutiny とそのサブスクリプションプロトコルの lazy (遅延) 性の側面から来ています。 これについての詳細は Mutiny の ドキュメント を参照してください。

サーバー送信イベント (SSE) のサポート

SSE イベントは、結果の型を io.smallrye.mutiny.Multi と宣言するだけで使用できます。

最も簡単な例

package org.acme.rest.client;

import io.smallrye.mutiny.Multi;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@Path("/sse")
@RegisterRestClient(configKey = "some-api")
public interface SseClient {
     @GET
     @Produces(MediaType.SERVER_SENT_EVENTS)
     Multi<String> get();
}

SSE 結果のストリーミングに関係するすべての IO は、ノンブロッキング方式で実行されます。

結果は文字列に限定されません。たとえば、サーバーが各イベントの JSON ペイロードを返すと、Quarkus はそれを Multi で使用される汎用型に自動的にデシリアライズします。

ユーザーは、 org.jboss.resteasy.reactive.client.SseEvent 型を使用して、SSE イベント全体にアクセスすることもできます。

イベントペイロードが Long 値である簡単な例を次に示します。

package org.acme.rest.client;

import io.smallrye.mutiny.Uni;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.client.SseEvent;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;

@Path("/sse")
@RegisterRestClient(configKey = "some-api")
public interface SseClient {
     @GET
     @Produces(MediaType.SERVER_SENT_EVENTS)
     Multi<SseEvent<Long>> get();
}

イベントのフィルタリング

場合によっては、SSE イベントのストリームに、クライアントから返されるべきではないイベントが含まれることがあります。この例としては、基盤となる TCP 接続を開いたままにするために、サーバーがハートビートイベントを送信することが挙げられます。 REST Client は、 @org.jboss.resteasy.reactive.client.SseEventFilter を提供することで、このようなイベントをフィルタリングすることをサポートします。

以下はハートビートイベントをフィルタリングする例です。

package org.acme.rest.client;

import io.smallrye.mutiny.Uni;
import java.util.function.Predicate;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.client.SseEvent;
import org.jboss.resteasy.reactive.client.SseEventFilter;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;

@Path("/sse")
@RegisterRestClient(configKey = "some-api")
public interface SseClient {

     @GET
     @Produces(MediaType.SERVER_SENT_EVENTS)
     @SseEventFilter(HeartbeatFilter.class)
     Multi<SseEvent<Long>> get();


     class HeartbeatFilter implements Predicate<SseEvent<String>> {

        @Override
        public boolean test(SseEvent<String> event) {
            return !"heartbeat".equals(event.id());
        }
     }
}

カスタムヘッダーのサポート

REST 呼び出しのカスタムヘッダーを指定する方法はいくつかあります。

  • @RegisterClientHeaders アノテーションを用いて ClientHeadersFactory または ReactiveClientHeadersFactory を登録する方法。

  • QuarkusRestClientBuilder.clientHeadersFactory(factory) メソッドを使用して、 ClientHeadersFactory または ReactiveClientHeadersFactory をプログラムで登録する方法。

  • @ClientHeaderParam でヘッダーの値を指定する方法。

  • @HeaderParam でヘッダーの値を指定する方法。

以下のコードは、これらの各手法の使用方法を示しています。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import java.util.Set;
import io.quarkus.rest.client.reactive.NotBody;

@Path("/extensions")
@RegisterRestClient
@RegisterClientHeaders(RequestUUIDHeaderFactory.class) (1)
@ClientHeaderParam(name = "my-header", value = "constant-header-value") (2)
@ClientHeaderParam(name = "computed-header", value = "{org.acme.rest.client.Util.computeHeader}") (3)
public interface ExtensionsService {

    @GET
    @ClientHeaderParam(name = "header-from-properties", value = "${header.value}") (4)
    @ClientHeaderParam(name = "header-from-method-param", value = "Bearer {token}") (5)
    Set<Extension> getById(@QueryParam("id") String id, @HeaderParam("jaxrs-style-header") String headerValue, @NotBody String token); (6)
}
1 クラスごとに存在できる ClientHeadersFactory は 1 つだけです。これを使用すると、カスタムヘッダーを追加できるだけでなく、既存のヘッダーを変換することもできます。ファクトリーの例については、以下の RequestUUIDHeaderFactory クラスを参照してください。
2 @ClientHeaderParam は、クライアントインターフェイスとメソッドで使用できます。また、一定のヘッダー値を指定できます…​。
3 …​ また、ヘッダーの値を計算するメソッドの名前を指定することもできます。このメソッドは、静的メソッドまたはこのインターフェイス内のデフォルトメソッドのいずれかにすることができます。メソッドは、パラメーターなし、単一の String パラメーター、または単一の io.quarkus.rest.client.reactive.ComputedParamContext パラメーターを取ることができます (これは、メソッドのパラメーターに基づいてヘッダーを計算する必要があるコードに非常に便利で、 @io.quarkus.rest.client.reactive.NotBody と自然に補完し合います)。
4 …​ また、アプリケーションの設定値も使用します。
5 …​ または、逐語的なテキスト、メソッドパラメーター (名前で参照)、設定値 (前述のとおり)、メソッド呼び出し (前述のとおり) の任意の組み合わせでもかまいません。
6 …​ または、通常の Jakarta REST `@HeaderParam`アノテーション付き引数として使用できます。

Kotlin を使用するときにデフォルトのメソッドを利用する場合は、Java のデフォルトのインターフェイス機能を使用するように Kotlin コンパイラーを設定する必要があります。 詳細は、こちら を参照してください。

ClientHeadersFactory は次のようになります。

package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.UUID;

@ApplicationScoped
public class RequestUUIDHeaderFactory implements ClientHeadersFactory {

    @Override
    public MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders, MultivaluedMap<String, String> clientOutgoingHeaders) {
        MultivaluedMap<String, String> result = new MultivaluedHashMap<>();
        result.add("X-request-uuid", UUID.randomUUID().toString());
        return result;
    }
}

上の例のように、 @Singleton@ApplicationScoped などのスコープを定義するアノテーションを付けることで、 ClientHeadersFactory の実装を CDI Bean にすることができます。

${header.value} に値を指定するには、 application.properties に単に以下のように記述します。

header.value=value of the header

また、ブロッキング操作を実行できる ClientHeadersFactory のリアクティブフレーバーがあります。例えば:

package org.acme.rest.client;

import io.smallrye.mutiny.Uni;

import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.UUID;

@ApplicationScoped
public class GetTokenReactiveClientHeadersFactory extends ReactiveClientHeadersFactory {

    @Inject
    Service service;

    @Override
    public Uni<MultivaluedMap<String, String>> getHeaders(
            MultivaluedMap<String, String> incomingHeaders,
            MultivaluedMap<String, String> clientOutgoingHeaders) {
        return Uni.createFrom().item(() -> {
            MultivaluedHashMap<String, String> newHeaders = new MultivaluedHashMap<>();
            // perform blocking call
            newHeaders.add(HEADER_NAME, service.getToken());
            return newHeaders;
        });
    }
}

HTTP Basic Auth を使用する場合、 @io.quarkus.rest.client.reactive.ClientBasicAuth アノテーションを使用すると、 必要な Authorization ヘッダーの設定が大幅に簡素化されます。

以下に、非常に簡単な例を示します。

@ClientBasicAuth(username = "${service.username}", password = "${service.password}")
public interface SomeClient {

}

ここで、 service.usernameservice.password は、実行時にユーザー名とパスワードを設定して呼び出されるサービスへのアクセスを許可する設定プロパティーです。

デフォルトのヘッダーファクトリー

@RegisterClientHeaders アノテーションは、カスタムファクトリーを指定せずに使用することもできます。その場合、 DefaultClientHeadersFactoryImpl ファクトリーが使用されます。 REST リソースから REST クライアント呼び出しを行う場合、このファクトリーは、 org.eclipse.microprofile.rest.client.propagateHeaders 設定プロパティーにリストされているすべてのヘッダーをリソースリクエストからクライアントリクエストに伝播させます。個々のヘッダー名はコンマで区切られます。

@Path("/extensions")
@RegisterRestClient
@RegisterClientHeaders
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);

    @GET
    CompletionStage<Set<Extension>> getByIdAsync(@QueryParam("id") String id);
}
org.eclipse.microprofile.rest.client.propagateHeaders=Authorization,Proxy-Authorization

リクエストのカスタマイズ

REST Client は、フィルターを介してサーバーに送信される最終リクエストのさらなるカスタマイズをサポートします。フィルターは、インターフェイス ClientRequestFilter または ResteasyReactiveClientRequestFilter のいずれかを実装する必要があります。

リクエストをカスタマイズする簡単な例として、カスタムヘッダーを追加することが挙げられます。

@Provider
public class TestClientRequestFilter implements ClientRequestFilter {

    @Override
    public void filter(ClientRequestContext requestContext) {
        requestContext.getHeaders().add("my_header", "value");
    }
}

次に、 @RegisterProvider アノテーションを使用してフィルターを登録できます。

@Path("/extensions")
@RegisterProvider(TestClientRequestFilter.class)
public interface ExtensionsService {

    // ...
}

または、 .register() メソッドをプログラムで使用します。

QuarkusRestClientBuilder.newBuilder()
    .register(TestClientRequestFilter.class)
    .build(ExtensionsService.class)

jakarta.ws.rs.ext.Providers インスタンスをフィルターに注入する

jakarta.ws.rs.ext.Providers は、現在のクライアントのプロバイダー・インスタンスを検索する必要がある場合に便利です。

次のようにして、リクエストコンテキストからフィルター内の Providers インスタンスを取得できます。

@Provider
public class TestClientRequestFilter implements ClientRequestFilter {

    @Override
    public void filter(ClientRequestContext requestContext) {
        Providers providers = ((ResteasyReactiveClientRequestContext) requestContext).getProviders();
        // ...
    }
}

または、 ClientRequestFilter インターフェイスの代わりに ResteasyReactiveClientRequestFilter インターフェイスを実装して、 ResteasyReactiveClientRequestContext コンテキストを直接提供することもできます。

@Provider
public class TestClientRequestFilter implements ResteasyReactiveClientRequestFilter {

    @Override
    public void filter(ResteasyReactiveClientRequestFilter requestContext) {
        Providers providers = requestContext.getProviders();
        // ...
    }
}

REST Client Jackson の ObjectMapper のカスタマイズ

REST Client は、 @ClientObjectMapper アノテーションを使用して、クライアント専用のカスタム ObjectMapper を追加することをサポートします。

簡単な例として、次のようにして REST Client Jackson エクステンションにカスタム ObjectMapper を提供することが挙げられます。

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);

    @ClientObjectMapper (1)
    static ObjectMapper objectMapper(ObjectMapper defaultObjectMapper) { (2)
        return defaultObjectMapper.copy() (3)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .disable(DeserializationFeature.UNWRAP_ROOT_VALUE);
    }
}
1 メソッドには @ClientObjectMapper アノテーションを付ける必要があります。
2 これは静的メソッドである必要があります。また、 defaultObjectMapper パラメーターは CDI を介して解決されます。見つからない場合は、実行時に例外がスローされます。
3 この例では、デフォルトのオブジェクトマッパーのコピーを作成しています。デフォルトのオブジェクトマッパーは 絶対に 変更しないでください。代わりにコピーを作成してください。

例外処理

MicroProfile REST Client 仕様では、HTTP 応答を例外に変換することを目的とした org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper が導入されています。

上記の ExtensionsService にこのような ResponseExceptionMapper を実装する簡単な例は、次のとおりです。

public class MyResponseExceptionMapper implements ResponseExceptionMapper<RuntimeException> {

    @Override
    public RuntimeException toThrowable(Response response) {
        if (response.getStatus() == 500) {
            throw new RuntimeException("The remote service responded with HTTP 500");
        }
        return null;
    }
}

ResponseExceptionMapper は、 ResponseExceptionMapper 実装が呼び出される優先度を決定するために使用される getPriority メソッドも定義します (getPriority の値が小さい実装が最初に呼び出されます)。 toThrowable が例外を返す場合、その例外が出力されます。 null が返された場合、チェーン内の ResponseExceptionMapper の次の実装が呼び出されます (存在する場合)。

上記のクラスは、REST Client によって自動的に使用されることはありません。アプリケーションのすべての REST Client で使用できるようにするには、クラスに @Provider アノテーションを付ける必要があります (quarkus.rest-client.provider-autodiscoveryfalse に設定されていない場合)。 または、例外処理クラスを特定の REST Client インターフェイスにのみ適用する必要がある場合は、インターフェイスに @RegisterProvider(MyResponseExceptionMapper.class) でアノテーションを付けるか、適切な quarkus.rest-client 設定グループの providers プロパティー設定を使用して登録できます。

@ClientExceptionMapper を使用する

400 以上の HTTP 応答コードを変換する簡単な方法は、 @ClientExceptionMapper アノテーションを使用することです。

上記で定義された ExtensionsService REST Client インターフェイスの場合、 @ClientExceptionMapper の使用例は次のようになります。

@Path("/extensions")
@RegisterRestClient
public interface ExtensionsService {

    @GET
    Set<Extension> getById(@QueryParam("id") String id);

    @GET
    CompletionStage<Set<Extension>> getByIdAsync(@QueryParam("id") String id);

    @ClientExceptionMapper
    static RuntimeException toException(Response response) {
        if (response.getStatus() == 500) {
            return new RuntimeException("The remote service responded with HTTP 500");
        }
        return null;
    }
}

当然、この処理は REST クライアントごとに行われます。 @ClientExceptionMapper は、 priority 属性が設定されておらず、すべてのハンドラーを呼び出す通常のルールが適用される場合、デフォルトの優先度を使用します。

@ClientExceptionMapper でアノテーションされたメソッドは、 java.lang.reflect.Method パラメーターを取れます。これは、例外対応のコードは、呼び出されて例外を発生したREST Client メソッドを知る場合に便利です。

例外マッパーでの@Blockingアノテーションの使用

REST Client メソッドの戻り値の型として InputStream を使用する必要がある場合 (大量のデータを読み取る必要がある場合など) は、以下のようになります。

@Path("/echo")
@RegisterRestClient
public interface EchoClient {

    @GET
    InputStream get();
}

これは期待どおりに動作しますが、この InputStream オブジェクトをカスタム例外マッパーで読み取ろうとすると、 BlockingNotAllowedException 例外が発生します。これは、 ResponseExceptionMapper クラスがデフォルトでイベントループスレッドエグゼキューターで実行され、IO 操作を実行できないためです。

例外マッパーをブロッキングにするには、例外マッパーに @Blocking アノテーションを付けます。

@Provider
@Blocking (1)
public class MyResponseExceptionMapper implements ResponseExceptionMapper<RuntimeException> {

    @Override
    public RuntimeException toThrowable(Response response) {
        if (response.getStatus() == 500) {
            response.readEntity(String.class); (2)
            return new RuntimeException("The remote service responded with HTTP 500");
        }
        return null;
    }
}
1 @Blocking アノテーションにより、MyResponseExceptionMapper例外マッパーはワーカースレッドプールで実行されることになります。
2 ワーカースレッドプールでマッパーを実行しているため、エンティティの読み取りが許可されるようになりました。

なお、@ClientExceptionMapperを使用する場合は、 @Blocking アノテーションを使用することも可能です:

@Path("/echo")
@RegisterRestClient
public interface EchoClient {

    @GET
    InputStream get();

    @ClientExceptionMapper
    @Blocking
    static RuntimeException toException(Response response) {
        if (response.getStatus() == 500) {
            response.readEntity(String.class);
            return new RuntimeException("The remote service responded with HTTP 500");
        }
        return null;
    }
}

デフォルトマッパーを無効にする

REST Client 仕様で義務付けられているように、HTTP ステータスコードが 400 より大きい場合に例外をスローするデフォルトの例外マッパーが含まれています。 クライアントが通常のオブジェクトを返す場合にはこの動作は問題ありませんが、クライアントが jakarta.ws.rs.core.Response を返す必要がある場合には、ほとんど直感的ではありません。 (呼び出し元が HTTP ステータスコードの処理方法を決定できるようにすることを目的としています)。

このため、REST Client には、宣言的な方法で REST クライアントを使用するときにデフォルトのマッパーを無効にするために使用できる disable-default-mapper というプロパティーが含まれています。

このようなクライアントは、たとえば以下のようになります。

    @Path("foo")
    @RegisterRestClient(configKey = "bar")
    public interface Client {
        @GET
        Response get();
    }

デフォルトの例外マッパーは、 quarkus.rest-client.bar.disable-default-mapper=true を設定して、キー bar で設定された REST Client の例外マッパーを無効にすることで無効にできます。

REST Client を作成するためのプログラム的なアプローチを使用する場合、 QuarkusRestClientBuilder は、同じ機能を提供する disableDefaultMapper という名前 のメソッドを提供します。

マルチパートフォームのサポート

マルチパートメッセージの送信

REST Client を使用すると、データをマルチパートフォームで送信できます。このようにして、たとえば、 ファイルを効率的に送信できます。

データをマルチパートフォームとして送信するには、通常の @RestForm (または @FormParam ) アノテーションを使用します:

    @POST
    @Path("/binary")
    String sendMultipart(@RestForm File file, @RestForm String otherField);

FilePathbyte[]BufferFileUpload として指定されたパラメーターはファイルとして送信され、デフォルトでは application/octet-stream MIME 型になります。他の @RestForm パラメーター型はデフォルトで text/plain MIME 型になります。 @PartType アノテーションを使用して、これらのデフォルトをオーバーライドできます。

当然ながら、これらのパラメーターを含むクラスにまとめられます:

    public static class Parameters {
        @RestForm
        File file;

        @RestForm
        String otherField;
    }

    @POST
    @Path("/binary")
    String sendMultipart(Parameters parameters);

@RestForm アノテーションが付けられた FilePathbyte[]Buffer、または FileUpload 型のパラメーター、 および @PartType アノテーションが付けられたパラメーターは、 @Consumes が指定されていない場合、自動的にメソッドに @Consumes(MediaType.MULTIPART_FORM_DATA) が 暗黙的に付与されます。

マルチパートではない @RestForm パラメーターがある場合は、 @Consumes(MediaType.APPLICATION_FORM_URLENCODED) になります。

フォームデータのエンコードには、いくつかのモードがあります。デフォルトでは、 Rest Client は RFC1738 を使用します。 クライアントレベルで、 io.quarkus.rest.client.multipart-post-encoder-mode RestBuilder プロパティーを HttpPostRequestEncoder.EncoderMode の選択した値に設定するか、 application.propertiesquarkus.rest-client.multipart-post-encoder-mode を指定して、 モードをオーバーライドできます。後者は @RegisterRestClient アノテーションで作成された クライアントに対してのみ機能することに注意してください。 利用可能なすべてのモードは、Netty ドキュメント に記載されています。

また、 @PartType アノテーションを指定することで、JSON のマルチパートも送信できます。

    public static class Person {
        public String firstName;
        public String lastName;
    }

    @POST
    @Path("/json")
    String sendMultipart(@RestForm @PartType(MediaType.APPLICATION_JSON) Person person);

プログラムによるマルチパートフォームの作成

マルチパートコンテンツをプログラムで構築する必要がある場合、REST Client は次のように REST Client で使用できる ClientMultipartForm を提供します。

public interface MultipartService {

  @POST
  @Path("/multipart")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.APPLICATION_JSON)
  Map<String, String> multipart(ClientMultipartForm dataParts);
}

このクラスとサポートされているメソッドの詳細は、ClientMultipartForm の javadoc を参照してください。

受信したマルチパートオブジェクトをクライアントリクエストに変換する

ClientMultipartForm を作成する良い例は、サーバーの MultipartFormDataInput (Quarkus REST によって受信されたマルチパートリクエストを表す) から作成されるものです。その目的は、任意の変更を許可しながらリクエストをダウンストリームに伝播することです。

public ClientMultipartForm buildClientMultipartForm(MultipartFormDataInput inputForm) (1)
    throws IOException {
  ClientMultipartForm multiPartForm = ClientMultipartForm.create(); (2)
  for (Entry<String, Collection<FormValue>> attribute : inputForm.getValues().entrySet()) {
    for (FormValue fv : attribute.getValue()) {
      if (fv.isFileItem()) {
        final FileItem fi = fv.getFileItem();
        String mediaType = Objects.toString(fv.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE),
            MediaType.APPLICATION_OCTET_STREAM);
        if (fi.isInMemory()) {
          multiPartForm.binaryFileUpload(attribute.getKey(), fv.getFileName(),
              Buffer.buffer(IOUtils.toByteArray(fi.getInputStream())), mediaType); (3)
        } else {
          multiPartForm.binaryFileUpload(attribute.getKey(), fv.getFileName(),
              fi.getFile().toString(), mediaType); (4)
        }
      } else {
        multiPartForm.attribute(attribute.getKey(), fv.getValue(), fv.getFileName()); (5)
      }
    }
  }
  return multiPartForm;
}
1 MultipartFormDataInput は、受信したマルチパートリクエストを表す Quarkus REST (Server) 型です。
2 ClientMultipartForm が作成されました。
3 メモリー内のファイル属性を表すリクエスト属性に対して FileItem 属性が作成されます。
4 FileItem 属性は、ファイルシステムに保存されたファイル属性を表すリクエスト属性に対して作成されます。
5 FileItem でない場合は、ファイル以外の属性が ClientMultipartForm に直接追加されます。

同様に、受信したサーバーのマルチパート要求が既知で、次のようになる場合、

public class Request { (1)

  @RestForm("files")
  @PartType(MediaType.APPLICATION_OCTET_STREAM)
  List<FileUpload> files;

  @RestForm("jsonPayload")
  @PartType(MediaType.TEXT_PLAIN)
  String jsonPayload;
}

ClientMultipartForm は次のように簡単に作成できます。

public ClientMultipartForm buildClientMultipartForm(Request request) { (1)
  ClientMultipartForm multiPartForm = ClientMultipartForm.create();
  multiPartForm.attribute("jsonPayload", request.getJsonPayload(), "jsonPayload"); (2)
  request.getFiles().forEach(fu -> {
    multiPartForm.fileUpload(fu); (3)
  });
  return multiPartForm;
}
1 サーバー部分が受け入れるリクエストを表す Request
2 jsonPayload 属性が ClientMultipartForm に直接追加されます。
3 リクエストの FileUpload から fileUpload が作成されます。

同じ名前を使用するマルチパートデータを送信する場合、クライアントとサーバーが同じマルチパートエンコーダーモードを使用していない場合、問題が発生する可能性があります。 デフォルトでは、REST Client は RFC1738 を使用しますが、状況に応じて、クライアントを HTML5 または RFC3986 モードで設定する必要がある場合があります。

この設定は、 quarkus.rest-client.multipart-post-encoder-mode プロパティーを介して実現できます。

マルチパートメッセージの受信

REST Client は、マルチパートメッセージの受信もサポートしています。 送信と同様に、マルチパートレスポンスを解析するには、レスポンスデータを記述するクラスを作成する必要があります。以下に例を示します。

public class FormDto {
    @RestForm (1)
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public File file;

    @FormParam("otherField") (2)
    @PartType(MediaType.TEXT_PLAIN)
    public String textProperty;
}
1 省略形の @RestForm アノテーションを使用して、マルチパートフォームの一部としてフィールドを作成します
2 標準の @FormParam も使用できます。マルチパートパートの名前を上書きできます。

次に、呼び出しに対応するインターフェイスメソッドを作成し、 FormDto を返すようにします。

    @GET
    @Produces(MediaType.MULTIPART_FORM_DATA)
    @Path("/get-file")
    FormDto data receiveMultipart();

現時点では、マルチパート応答のサポートには次の制限があります。

  • マルチパート応答で送信されたファイルは、 FilePath、および FileDownload にのみ解析できます。

  • 応答型の各フィールドには @PartType アノテーションを付ける必要があります - このアノテーションのないフィールドは無視されます

REST Client は、マルチパートの戻り値の型として使用されるクラスを事前に認識する必要があります。 multipart/form-data を生成するインターフェイスメソッドがある場合、戻り値の型は自動的に検出されます。ただし、 ClientBuilder API を使用して応答をマルチパートとして解析する場合は、DTO クラスに @MultipartForm のアノテーションを付ける必要があります。

ダウンロードしたファイルは自動的に削除されず、多くのディスク領域を占有する可能性があります。作業が終わったら、ファイルを削除することを検討してください。

マルチパート混合/OData の使用状況

アプリケーションが、 OData と呼ばれる特別なプロトコルを使用してエンタープライズシステム (CRM システムなど) と対話する必要があることは珍しくありません。 このプロトコルは基本的に、REST Client で動作するためにいくつかのグルーコードを必要とするカスタム HTTP Content-Type を使用します (本体の作成は完全にアプリケーション次第であり、REST Client はあまり役に立ちません)。

例は次のようになります:

@Path("/crm")
@RegisterRestClient
public interface CRMService {

    @POST
    @ClientHeaderParam(name = "Content-Type", value = "{calculateContentType}")  (1)
    String performBatch(@HeaderParam("Authorization") String accessToken, @NotBody String batchId, String body); (2)

    default String calculateContentType(ComputedParamContext context) {
        return "multipart/mixed;boundary=batch_" + context.methodParameters().get(1).value(); (3)
    }
}

コードでは次の部分を使用します。

1 @ClientHeaderParam(name = "Content-Type", value = "{calculateContentType}") は、インターフェイスの calculateContentType デフォルトメソッドを呼び出して Content-Type ヘッダーが作成されるようにします。
2 前述のパラメーターは、HTTP ヘッダーの構築を支援するためにのみ使用されるため、 @NotBody アノテーションを付ける必要があります。
3 context.methodParameters().get(1).value() により、 calculateContentType メソッドは REST Client メソッドに渡される適切なメソッドパラメーターを取得できるようになります。

前述したように、サービスの要件に準拠するには、アプリケーションコードによって body パラメーターを適切に作成する必要があります。

圧縮メッセージの受信

REST Client は GZIP を使用した圧縮メッセージの受信もサポートしており、設定で有効にすることができます。 この機能が有効で、サーバがヘッダ Content-Encoding: gzip を含む応答を返すと、REST Client は自動的にコンテンツをデコードし、メッセージの処理を進めます。

コンフィギュレーションの例は次のようになります:

# global configuration is used for all clients
quarkus.rest-client.enable-compression=true

# per-client configuration overrides the global settings for a specific client
quarkus.rest-client.my-client.enable-compression=true

RESTクライアント固有のプロパティが設定されていない場合、RESTクライアントはQuarkus全体の quarkus.http.enable-compression 設定プロパティ(デフォルトは false )にフォールバックします。

プロキシーサポート

REST Client はプロキシ経由でのリクエスト送信をサポートしています。 JVMの設定を尊重しますが、両方を指定することもできます:

  • グローバルクライアントプロキシー設定、 quarkus.rest-client.proxy-addressquarkus.rest-client.proxy-userquarkus.rest-client.proxy-passwordquarkus.rest-client.non-proxy-hosts

  • クライアントごとのプロキシー設定は、 quarkus.rest-client.<my-client>.proxy-address などで行います。これらは CDI で注入されたクライアント、つまり @RegisterRestClient を使って作成されたクライアントにのみ適用されます。

proxy-address がクライアントレベルで設定されている場合、クライアントは特定のプロキシー設定を使用します。プロキシー設定は、グローバル設定または JVM プロパティーから伝播されません。

クライアントに proxy-address が設定されていないが、グローバルレベルで設定されている場合、クライアントはグローバル設定を使用します。 それ以外の場合、クライアントは JVM 設定を使用します。

プロキシーを設定するための設定例:

# global proxy configuration is used for all clients
quarkus.rest-client.proxy-address=localhost:8182
quarkus.rest-client.proxy-user=<proxy user name>
quarkus.rest-client.proxy-password=<proxy password>
quarkus.rest-client.non-proxy-hosts=example.com

# per-client configuration overrides the global settings for a specific client
quarkus.rest-client.my-client.proxy-address=localhost:8183
quarkus.rest-client.my-client.proxy-user=<proxy user name>
quarkus.rest-client.my-client.proxy-password=<proxy password>
quarkus.rest-client.my-client.url=...
MicroProfile REST Client 仕様では、プロキシー資格情報の設定は許可されていません。プログラムでプロキシーユーザーとプロキシーパスワードを指定するには、 RestClientBuilderRestClientBuilderImpl にキャストする必要があります。

開発モードのローカルプロキシー

開発モードで REST クライアントを使用する際、Quarkus はパススループロキシーを立ち上げる機能を備えており、これを Wireshark (または類似のツール) のターゲットとして使用することで、 REST クライアントから発信されるすべてのトラフィックをキャプチャーすることができます (特に REST Client が HTTPS サービスに対して使用される場合に有用です)。

この機能は、プロキシーが必要なクライアントに対応する configKey の enable-local-proxy 設定オプションを設定するだけで有効化できます。 以下に例を示します。

quarkus.rest-client.my-client.enable-local-proxy=true

REST クライアントが設定キーを使用しない場合 (たとえば、 QuarkusRestClientBuilder を介してプログラムで作成される場合など)、代わりにクラス名を使用できます。 以下に例を示します。

quarkus.rest-client."org.acme.SomeClient".enable-local-proxy=true

プロキシーがリッスンしているポートは、起動ログで確認できます。エントリーの例は次のとおりです。

Started HTTP proxy server on http://localhost:38227 for REST Client 'org.acme.SomeClient'

アプリケーションをパッケージ化して実行する

アプリケーションを実行します:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

このエクステンションに関する基本的な情報を含む JSON オブジェクトが表示されるはずです。

いつものように、アプリケーションは以下の方法でパッケージ化されます。

コマンドラインインタフェース
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

そして、 java -jar target/quarkus-app/quarkus-run.jar で実行されます。

次のようにネイティブ実行可能ファイルを生成することもできます。

コマンドラインインタフェース
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

トラフィックの記録

REST Client は、送信したリクエストと受信したレスポンスをログに記録できます。 ロギングを有効にするには、 application.propertiesquarkus.rest-client.logging.scope プロパティを追加し、次のように設定します:

  • リクエストと応答の内容をログに記録する request-response 、または

  • all は、基礎となるライブラリーの低レベルのロギングも有効にします。

HTTP メッセージには大きな本文が含まれる可能性があるため、ログに記録される本文の文字数を制限します。デフォルトの制限は 100 ですが、 quarkus.rest-client.logging.body-limit を指定することで変更できます。

REST Client は、レベル DEBUG でトラフィックをロギングし、ロガー プロパティを変更しません。この機能を使用するには、ロガー設定を調整する必要があります。

これらの設定プロパティーは、CDI によって注入されたすべてのクライアントに対してグローバルに機能します。 特定の宣言型クライアントのロギングを設定する場合は、 quarkus.rest-client."client".logging.* プロパティーとも呼ばれる、名前付き "client" プロパティーを指定して設定する必要があります。

ロギング設定の例:

quarkus.rest-client.logging.scope=request-response
quarkus.rest-client.logging.body-limit=50

quarkus.rest-client.extensions-api.scope=all

quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG
quarkus.log.console.level=DEBUG

REST Client はデフォルトの ClientLogger 実装を使用します。この実装は、カスタム実装に置き換えることができます。

QuarkusRestClientBuilder を使用してプログラムでクライアントを設定する場合、 ClientLoggerclientLogger メソッドで設定されます。

@RegisterRestClient を使用する宣言型クライアントの場合、 ClientLogger を実装する CDI Bean を提供するだけで、そのロガーをクライアントが使用できるようになります。

テストのためのクライアントのモッキング

@RestClient アノテーションが挿入されたクライアントを使用する場合は、テスト用に簡単にモックすることができます。 Mockito の @InjectMock または QuarkusMock でそれを行うことができます。

このセクションでは、クライアントをモックに置き換える方法を示します。Quarkus でモッキングがどのように機能するかをより深く理解したい場合は、 Mocking CDI beans のブログ投稿を参照してください。

@QuarkusIntegrationTest を使用した場合、モッキングは動作しません。

次のクライアントがあると仮定します。

package io.quarkus.it.rest.client.main;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;


@Path("/")
@RegisterRestClient
public interface Client {
    @GET
    String get();
}

InjectMock でモックする

テスト用にクライアントをモックする最も簡単な方法は、Mockito と @InjectMock を使用することです。

まず、以下の依存関係をアプリケーションに追加します。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5-mockito</artifactId>
    <scope>test</scope>
</dependency>
build.gradle
testImplementation("io.quarkus:quarkus-junit5-mockito")

次に、テストで @InjectMock を使用して、モックを作成して挿入できます。

package io.quarkus.it.rest.client.main;

import static org.mockito.Mockito.when;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class InjectMockTest {

    @InjectMock
    @RestClient
    Client mock;

    @BeforeEach
    public void setUp() {
        when(mock.get()).thenReturn("MockAnswer");
    }

    @Test
    void doTest() {
        // ...
    }
}

QuarkusMock でモックする

Mockito がニーズを満たさない場合は、 QuarkusMock を使用してプログラムでモックを作成できます。例:

package io.quarkus.it.rest.client.main;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusMock;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class QuarkusMockTest {

    @BeforeEach
    public void setUp() {
        Client customMock = new Client() { (1)
            @Override
            public String get() {
                return "MockAnswer";
            }
        };
        QuarkusMock.installMockForType(customMock, Client.class, RestClient.LITERAL); (2)
    }
    @Test
    void doTest() {
        // ...
    }
}
1 ここでは、手動で作成したクライアントインターフェイスの実装を使用して、実際のクライアントを置き換えます
2 RestClient.LITERALinstallMockForType メソッドの最後の引数として渡される必要があることに注意してください

テストにモックHTTPサーバーを使用する

テストを実行する際にモック HTTP サーバーを設定することは、一般的なテストパターンです。 そのようなサーバーの例としては、WiremockHoverfly があります。 このセクションでは、ここまでで開発した ExtensionsService をテストするために Wiremock を活用する方法を示します。

最初に、 Wiremock をテストの依存関係として追加する必要があります。 Maven プロジェクトの場合は以下のようになります。

pom.xml
<dependency>
    <groupId>org.wiremock</groupId>
    <artifactId>wiremock</artifactId>
    <scope>test</scope>
    <version>${wiremock.version}</version> (1)
</dependency>
1 適切なWiremockバージョンを使用してください。利用可能なすべてのバージョンは、 こちら をご覧ください。
build.gradle
testImplementation("org.wiremock:wiremock:$wiremockVersion") (1)
1 適切なWiremockバージョンを使用してください。利用可能なすべてのバージョンは、 こちら をご覧ください。

Quarkus のテストを実行する前にサービスを開始する必要がある場合、Quarkus のテストでは、 @io.quarkus.test.common.QuarkusTestResource アノテーションを利用して、サービスを開始できる io.quarkus.test.common.QuarkusTestResourceLifecycleManager を指定し、 Quarkus が使用する設定値を提供します。

@QuarkusTestResource の詳細については、 ドキュメントのこの部分を参照してください。

WiremockExtensions という名前で、 QuarkusTestResourceLifecycleManager の実装を以下のように作成します。

package org.acme.rest.client;

import java.util.Map;

import com.github.tomakehurst.wiremock.WireMockServer;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

import static com.github.tomakehurst.wiremock.client.WireMock.*; (1)

public class WireMockExtensions implements QuarkusTestResourceLifecycleManager {  (2)

    private WireMockServer wireMockServer;

    @Override
    public Map<String, String> start() {
        wireMockServer = new WireMockServer();
        wireMockServer.start(); (3)

        wireMockServer.stubFor(get(urlEqualTo("/extensions?id=io.quarkus:quarkus-rest-client"))   (4)
                .willReturn(aResponse()
                        .withHeader("Content-Type", "application/json")
                        .withBody(
                            "[{" +
                            "\"id\": \"io.quarkus:quarkus-rest-client\"," +
                            "\"name\": \"REST Client\"" +
                            "}]"
                        )));

        wireMockServer.stubFor(get(urlMatching(".*")).atPriority(10).willReturn(aResponse().proxiedFrom("https://stage.code.quarkus.io/api")));   (5)

        return Map.of("quarkus.rest-client.\"org.acme.rest.client.ExtensionsService\".url", wireMockServer.baseUrl()); (6)
    }

    @Override
    public void stop() {
        if (null != wireMockServer) {
            wireMockServer.stop();  (7)
        }
    }
}
1 Wiremock パッケージのメソッドを静的にインポートすることで、テストが読みやすくなります。
2 start メソッドは、テストを実行する前に Quarkus によって呼び出され、テスト実行中に適用される設定プロパティーの Map を返します。
3 Wiremock を起動します。
4 /extensions?id=io.quarkus:quarkus-rest-client への呼び出しに対して特定のレスポンスを返すよう、Wiremock のスタブを設定します。
5 スタブ化されていないすべての HTTP 呼び出しは、実際のサービスを呼び出すことで処理されます。これはデモンストレーションを目的として行われているものであり、通常は実際のテストでは発生しません。
6 start メソッドはテストに適用される設定を返すので、 ExtensionsResource の実装で使用されるベース URL を制御する rest-client プロパティーを、 Wiremock がリクエストの着信をリッスンするベース URL に設定します。
7 すべてのテストが終了したら、Wiremock を終了します。

ExtensionsResourceTest クラスには、以下のようなアノテーションが必要です。

@QuarkusTest
@QuarkusTestResource(WireMockExtensions.class)
public class ExtensionsResourceTest {

}

@QuarkusTestResourceExtensionsResourceTest だけでなく、すべてのテストに適用されます。

既知の制限

REST Client エクステンションは、REST Client エクステンションのドロップインリプレースメントを目的としていますが、いくつかの違い や制限があります。

  • 新しいエクステンションのクライアントのデフォルトスコープは @ApplicationScoped ですが、 quarkus-resteasy-client のデフォルトは @Dependent です。 この動作を変更するには、 quarkus.rest-client.scope プロパティーを完全修飾形式のスコープ名に設定します。

  • SSLContext を設定することはできません。

  • ExecutorService の設定など、非ブロッキング実装には意味をなさないいくつかのことが機能しません

設定リファレンス

ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。

Configuration property

デフォルト

By default, RESTEasy Reactive uses text/plain content type for String values and application/json for everything else.

MicroProfile Rest Client spec requires the implementations to always default to application/json. This build item disables the "smart" behavior of RESTEasy Reactive to comply to the spec

Environment variable: QUARKUS_REST_CLIENT_DISABLE_SMART_PRODUCES

Show more

boolean

false

Whether providers (filters, etc.) annotated with jakarta.ws.rs.ext.Provider should be automatically registered for all the clients in the application.

Environment variable: QUARKUS_REST_CLIENT_PROVIDER_AUTODISCOVERY

Show more

boolean

true

ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。

Configuration property

デフォルト

If true, the extension will automatically remove the trailing slash in the paths if any. This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_REMOVES_TRAILING_SLASH

Show more

boolean

true

Mode in which the form data are encoded. Possible values are HTML5, RFC1738 and RFC3986. The modes are described in the Netty documentation

By default, Rest Client Reactive uses RFC1738.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_MULTIPART_POST_ENCODER_MODE

Show more

string

A string value in the form of : that specifies the HTTP proxy server hostname (or IP address) and port for requests of clients to use.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_PROXY_ADDRESS

Show more

string

Proxy username, equivalent to the http.proxy or https.proxy JVM settings.

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_PROXY_USER

Show more

string

Proxy password, equivalent to the http.proxyPassword or https.proxyPassword JVM settings.

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_PROXY_PASSWORD

Show more

string

Hosts to access without proxy, similar to the http.nonProxyHosts or https.nonProxyHosts JVM settings. Please note that unlike the JVM settings, this property is empty by default.

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_NON_PROXY_HOSTS

Show more

string

A timeout in milliseconds that REST clients should wait to connect to the remote endpoint.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_CONNECT_TIMEOUT

Show more

15000

A timeout in milliseconds that REST clients should wait for a response from the remote endpoint.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_READ_TIMEOUT

Show more

30000

If true, the REST clients will not provide additional contextual information (like REST client class and method names) when exception occurs during a client invocation.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_DISABLE_CONTEXTUAL_ERROR_MESSAGES

Show more

boolean

false

Default configuration for the HTTP user-agent header to use in all REST clients.

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_USER_AGENT

Show more

string

The HTTP headers that should be applied to all requests of the rest client.

Environment variable: QUARKUS_REST_CLIENT_HEADERS__HEADER_NAME_

Show more

Map<String,String>

The class name of the host name verifier. The class must have a public no-argument constructor.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_HOSTNAME_VERIFIER

Show more

string

The time in ms for which a connection remains unused in the connection pool before being evicted and closed. A timeout of 0 means there is no timeout.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_CONNECTION_TTL

Show more

int

The size of the connection pool for this client.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_CONNECTION_POOL_SIZE

Show more

int

50

If set to false disables the keep alive completely.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_KEEP_ALIVE_ENABLED

Show more

boolean

true

The maximum number of redirection a request can follow.

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_MAX_REDIRECTS

Show more

int

A boolean value used to determine whether the client should follow HTTP redirect responses.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_FOLLOW_REDIRECTS

Show more

boolean

Fully-qualified provider classnames to include in the client. The equivalent of the @RegisterProvider annotation.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_PROVIDERS

Show more

string

The CDI scope to use for injections of REST client instances. Value can be either a fully qualified class name of a CDI scope annotation (such as "jakarta.enterprise.context.ApplicationScoped") or its simple name (such as"ApplicationScoped").

Default scope for the rest-client extension is "Dependent" (which is the spec-compliant behavior).

Default scope for the rest-client-reactive extension is "ApplicationScoped".

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_SCOPE

Show more

string

An enumerated type string value with possible values of "MULTI_PAIRS" (default), "COMMA_SEPARATED", or "ARRAY_PAIRS" that specifies the format in which multiple values for the same query parameter is used.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_QUERY_PARAM_STYLE

Show more

multi-pairs, comma-separated, array-pairs

Set whether hostname verification is enabled. Default is enabled. This setting should not be disabled in production as it makes the client vulnerable to MITM attacks.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_VERIFY_HOST

Show more

boolean

The trust store location. Can point to either a classpath resource or a file.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_TRUST_STORE

Show more

string

The trust store password.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_TRUST_STORE_PASSWORD

Show more

string

The type of the trust store. Defaults to "JKS".

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_TRUST_STORE_TYPE

Show more

string

The key store location. Can point to either a classpath resource or a file.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_KEY_STORE

Show more

string

The key store password.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_KEY_STORE_PASSWORD

Show more

string

The type of the key store. Defaults to "JKS".

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_KEY_STORE_TYPE

Show more

string

The name of the TLS configuration to use.

If not set and the default TLS configuration is configured (quarkus.tls.*) then that will be used. If a name is configured, it uses the configuration from quarkus.tls.<name>.* If a name is configured, but no TLS configuration is found with that name then an error will be thrown.

If no TLS configuration is set, then the keys-tore, trust-store, etc. properties will be used.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_TLS_CONFIGURATION_NAME

Show more

string

If this is true then HTTP/2 will be enabled.

Environment variable: QUARKUS_REST_CLIENT_HTTP2

Show more

boolean

false

Configures two different things:

  • The max HTTP chunk size

  • The size of the chunk to be read when an InputStream is being used as an input

Can be overwritten by client-specific settings.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT_MAX_CHUNK_SIZE

Show more

MemorySize 

8k

Supports receiving compressed messages using GZIP. When this feature is enabled and a server returns a response that includes the header Content-Encoding: gzip, REST Client will automatically decode the content and proceed with the message handling.

This property is not applicable to the RESTEasy Client.

Can be overwritten by client-specific settings.

Environment variable: QUARKUS_REST_CLIENT_ENABLE_COMPRESSION

Show more

boolean

If the Application-Layer Protocol Negotiation is enabled, the client will negotiate which protocol to use over the protocols exposed by the server. By default, it will try to use HTTP/2 first and if it’s not enabled, it will use HTTP/1.1. When the property http2 is enabled, this flag will be automatically enabled.

Environment variable: QUARKUS_REST_CLIENT_ALPN

Show more

boolean

If true, the stacktrace of the invocation of the REST Client method is captured. This stacktrace will be used if the invocation throws an exception

Environment variable: QUARKUS_REST_CLIENT_CAPTURE_STACKTRACE

Show more

boolean

false

Scope of logging for the client.
WARNING: beware of logging sensitive data
The possible values are:

  • request-response - enables logging request and responses, including redirect responses

  • all - enables logging requests and responses and lower-level logging

  • none - no additional logging

This property is applicable to reactive REST clients only.

Environment variable: QUARKUS_REST_CLIENT_LOGGING_SCOPE

Show more

string

How many characters of the body should be logged. Message body can be large and can easily pollute the logs.

By default, set to 100.

This property is applicable to reactive REST clients only.

Environment variable: QUARKUS_REST_CLIENT_LOGGING_BODY_LIMIT

Show more

int

100

The CDI scope to use for injection. This property can contain either a fully qualified class name of a CDI scope annotation (such as "jakarta.enterprise.context.ApplicationScoped") or its simple name (such as "ApplicationScoped"). By default, this is not set which means the interface is not registered as a bean unless it is annotated with RegisterRestClient. If an interface is not annotated with RegisterRestClient and this property is set, then Quarkus will make the interface a bean of the configured scope.

Environment variable: QUARKUS_REST_CLIENT__CLIENTS__SCOPE

Show more

string

If set to true, then Quarkus will ensure that all calls from the REST client go through a local proxy server (that is managed by Quarkus). This can be very useful for capturing network traffic to a service that uses HTTPS.

This property is not applicable to the RESTEasy Client, only the Quarkus REST client (formerly RESTEasy Reactive client).

This property only applicable to dev and test mode.

Environment variable: QUARKUS_REST_CLIENT__CLIENTS__ENABLE_LOCAL_PROXY

Show more

boolean

false

This setting is used to select which proxy provider to use if there are multiple ones. It only applies if enable-local-proxy is true.

The algorithm for picking between multiple provider is the following:

  • If only the default is around, use it (its name is default)

  • If there is only one besides the default, use it

  • If there are multiple ones, fail

Environment variable: QUARKUS_REST_CLIENT__CLIENTS__LOCAL_PROXY_PROVIDER

Show more

string

If true, the extension will automatically remove the trailing slash in the paths if any. This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENTS__REMOVES_TRAILING_SLASH

Show more

boolean

true

The base URL to use for this service. This property or the uri property is considered required, unless the baseUri attribute is configured in the @RegisterRestClient annotation.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__URL

Show more

string

The base URI to use for this service. This property or the url property is considered required, unless the baseUri attribute is configured in the @RegisterRestClient annotation.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__URI

Show more

string

This property is only meant to be set by advanced configurations to override whatever value was set for the uri or url. The override is done using the REST Client class name configuration syntax.

This property is not applicable to the RESTEasy Client, only the Quarkus Rest client (formerly RESTEasy Reactive client).

Environment variable: QUARKUS_REST_CLIENT__CLIENT__OVERRIDE_URI

Show more

string

Map where keys are fully-qualified provider classnames to include in the client, and values are their integer priorities. The equivalent of the @RegisterProvider annotation.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__PROVIDERS

Show more

string

Timeout specified in milliseconds to wait to connect to the remote endpoint.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__CONNECT_TIMEOUT

Show more

Timeout specified in milliseconds to wait for a response from the remote endpoint.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__READ_TIMEOUT

Show more

A boolean value used to determine whether the client should follow HTTP redirect responses.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__FOLLOW_REDIRECTS

Show more

boolean

Mode in which the form data are encoded. Possible values are HTML5, RFC1738 and RFC3986. The modes are described in the Netty documentation

By default, Rest Client Reactive uses RFC1738.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__MULTIPART_POST_ENCODER_MODE

Show more

string

A string value in the form of : that specifies the HTTP proxy server hostname (or IP address) and port for requests of this client to use.

Use none to disable proxy

Environment variable: QUARKUS_REST_CLIENT__CLIENT__PROXY_ADDRESS

Show more

string

Proxy username.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__PROXY_USER

Show more

string

Proxy password.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__PROXY_PASSWORD

Show more

string

Hosts to access without proxy

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__NON_PROXY_HOSTS

Show more

string

An enumerated type string value with possible values of "MULTI_PAIRS" (default), "COMMA_SEPARATED", or "ARRAY_PAIRS" that specifies the format in which multiple values for the same query parameter is used.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__QUERY_PARAM_STYLE

Show more

multi-pairs, comma-separated, array-pairs

Set whether hostname verification is enabled. Default is enabled. This setting should not be disabled in production as it makes the client vulnerable to MITM attacks.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__VERIFY_HOST

Show more

boolean

The trust store location. Can point to either a classpath resource or a file.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__TRUST_STORE

Show more

string

The trust store password.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__TRUST_STORE_PASSWORD

Show more

string

The type of the trust store. Defaults to "JKS".

Environment variable: QUARKUS_REST_CLIENT__CLIENT__TRUST_STORE_TYPE

Show more

string

The key store location. Can point to either a classpath resource or a file.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__KEY_STORE

Show more

string

The key store password.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__KEY_STORE_PASSWORD

Show more

string

The type of the key store. Defaults to "JKS".

Environment variable: QUARKUS_REST_CLIENT__CLIENT__KEY_STORE_TYPE

Show more

string

The class name of the host name verifier. The class must have a public no-argument constructor.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__HOSTNAME_VERIFIER

Show more

string

The name of the TLS configuration to use.

If not set and the default TLS configuration is configured (quarkus.tls.*) then that will be used. If a name is configured, it uses the configuration from quarkus.tls.<name>.* If a name is configured, but no TLS configuration is found with that name then an error will be thrown.

If no TLS configuration is set, then the keys-tore, trust-store, etc. properties will be used.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__TLS_CONFIGURATION_NAME

Show more

string

The time in ms for which a connection remains unused in the connection pool before being evicted and closed. A timeout of 0 means there is no timeout.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__CONNECTION_TTL

Show more

int

The size of the connection pool for this client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__CONNECTION_POOL_SIZE

Show more

int

50

If set to false disables the keep alive completely.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__KEEP_ALIVE_ENABLED

Show more

boolean

The maximum number of redirection a request can follow.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__MAX_REDIRECTS

Show more

int

The HTTP headers that should be applied to all requests of the rest client.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__HEADERS__HEADER_NAME_

Show more

Map<String,String>

Set to true to share the HTTP client between REST clients. There can be multiple shared clients distinguished by name, when no specific name is set, the name __vertx.DEFAULT is used.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__SHARED

Show more

boolean

Set the HTTP client name, used when the client is shared, otherwise ignored.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__NAME

Show more

string

Configure the HTTP user-agent header to use.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__USER_AGENT

Show more

string

If this is true then HTTP/2 will be enabled.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__HTTP2

Show more

boolean

Configures two different things:

  • The max HTTP chunk size

  • The size of the chunk to be read when an InputStream is being read and sent to the server

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__MAX_CHUNK_SIZE

Show more

MemorySize 

8K

Supports receiving compressed messages using GZIP. When this feature is enabled and a server returns a response that includes the header Content-Encoding: gzip, REST Client will automatically decode the content and proceed with the message handling.

This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__ENABLE_COMPRESSION

Show more

boolean

If the Application-Layer Protocol Negotiation is enabled, the client will negotiate which protocol to use over the protocols exposed by the server. By default, it will try to use HTTP/2 first and if it’s not enabled, it will use HTTP/1.1. When the property http2 is enabled, this flag will be automatically enabled.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__ALPN

Show more

boolean

If true, the stacktrace of the invocation of the REST Client method is captured. This stacktrace will be used if the invocation throws an exception

Environment variable: QUARKUS_REST_CLIENT__CLIENT__CAPTURE_STACKTRACE

Show more

boolean

If set to true, then this REST Client will not the default exception mapper which always throws an exception if HTTP response code >= 400. This property is not applicable to the RESTEasy Client.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__DISABLE_DEFAULT_MAPPER

Show more

boolean

${microprofile.rest.client.disable.default.mapper:false}

Scope of logging for the client.
WARNING: beware of logging sensitive data
The possible values are:

  • request-response - enables logging request and responses, including redirect responses

  • all - enables logging requests and responses and lower-level logging

  • none - no additional logging

This property is applicable to reactive REST clients only.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__LOGGING_SCOPE

Show more

string

How many characters of the body should be logged. Message body can be large and can easily pollute the logs.

By default, set to 100.

This property is applicable to reactive REST clients only.

Environment variable: QUARKUS_REST_CLIENT__CLIENT__LOGGING_BODY_LIMIT

Show more

int

100

MemorySizeフォーマットについて

A size configuration option recognizes strings in this format (shown as a regular expression): [0-9]+[KkMmGgTtPpEeZzYy]?.

If no suffix is given, assume bytes.

関連コンテンツ