Skip to content

レスポンスのバリデーション

デフォルトでは、Ktor HTTPクライアントはHTTPステータスコードに基づいたレスポンスのバリデーションを行いません。 必要に応じて、以下の戦略を使用してレスポンスのバリデーションを有効にし、カスタマイズすることができます。

デフォルトのバリデーションを有効にする

Ktorでは、expectSuccess プロパティを true に設定することで、デフォルトのバリデーションを有効にできます。有効にすると、クライアントは成功(successful)以外のHTTPステータスコードを持つすべてのレスポンスに対して例外をスローします。

この動作は、クライアント設定でグローバルに有効にできます。

kotlin
import io.ktor.client.*
import io.ktor.client.engine.cio.*

val client = HttpClient(CIO) {
    expectSuccess = true
}

あるいは、リクエストごとに expectSuccess を有効にすることもできます。この場合、2xx以外のエラーレスポンスに対して以下の例外がスローされます。

カスタムバリデーション

デフォルトのバリデーション動作に加えて、HttpCallValidator プラグインを使用してカスタムのレスポンスバリデーションロジックを定義できます。これにより、成功(2xx)レスポンスを検証したり、2xx以外のレスポンスの処理方法をオーバーライドしたりできます。

HttpCallValidator をインストールするには、クライアント設定ブロック内で HttpResponseValidator 関数を呼び出します。

kotlin
val client = HttpClient(CIO) {
    HttpResponseValidator {
        // ...
    }
}

2xxレスポンスのバリデーション

デフォルトのバリデーションは、2xx以外のレスポンスに対してのみ例外をスローします。アプリケーションでより厳格なバリデーションが必要な場合は、validateResponse {} 関数を使用して成功レスポンスを検証できます。

以下の例では、サーバーはJSON形式のエラーペイロードを含む2xxレスポンスを返します。 validateResponse {} ブロックはレスポンスボディを検査し、エラーが検出された場合にカスタム例外をスローします。

kotlin
val client = HttpClient(CIO) {
    install(ContentNegotiation) { json() }
    HttpResponseValidator {
        validateResponse { response ->
            val error: Error = response.body()
            if (error.code != 0) {
                throw CustomResponseException(response, "Code: ${error.code}, message: ${error.message}")
            }
        }
    }
}

完全な例については、client-validate-2xx-response を参照してください。

2xx以外の例外の処理

2xx以外のレスポンス例外の処理方法をカスタマイズするには、handleResponseExceptionWithRequest {} 関数を使用します。

以下の例では、クライアントは 404 Not Found レスポンスに対して、デフォルトの ClientRequestException の代わりにカスタムの MissingPageException をスローします。

kotlin
class MissingPageException(response: HttpResponse, cachedResponseText: String) :
    ResponseException(response, cachedResponseText) {
    override val message: String = "Missing page: ${response.call.request.url}. " +
            "Status: ${response.status}."
}

fun main() {
    val client = HttpClient(CIO) {
        expectSuccess = true
        HttpResponseValidator {
            handleResponseExceptionWithRequest { exception, request ->
                val clientException = exception as? ClientRequestException ?: return@handleResponseExceptionWithRequest
                val exceptionResponse = clientException.response
                if (exceptionResponse.status == HttpStatusCode.NotFound) {
                    val exceptionResponseText = exceptionResponse.bodyAsText()
                    throw MissingPageException(exceptionResponse, exceptionResponseText)
                }
            }
        }
    }

    runBlocking {
        val httpResponse: HttpResponse = try {
            client.get("https://ktor.io/docs/missing-page.html")
        } catch (cause: ResponseException) {
            println(cause)
            cause.response
        }
    }
}

完全な例については、client-validate-non-2xx-response を参照してください。