Skip to content

回應驗證

預設情況下,Ktor HTTP 用戶端不會根據其 HTTP 狀態碼驗證回應。 如果需要,您可以使用以下策略啟用並自訂回應驗證:

啟用預設驗證

Ktor 允許您透過將 expectSuccess 屬性設定為 true 來啟用預設驗證。啟用時,用戶端會針對任何具有非成功 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 回應,用戶端會拋出自訂的 MissingPageException,而不是預設的 ClientRequestException

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