响应验证
默认情况下,Ktor HTTP 客户端不会根据 HTTP 状态码验证响应。 如果需要,你可以使用以下策略启用并自定义响应验证:
启用默认验证
Ktor 允许你通过将 expectSuccess 属性设置为 true 来启用默认验证。启用后,客户端将针对任何具有非成功 HTTP 状态码的响应抛出异常。
你可以在 客户端配置 中全局启用此行为:
import io.ktor.client.*
import io.ktor.client.engine.cio.*
val client = HttpClient(CIO) {
expectSuccess = true
}或者,你也可以按请求启用 expectSuccess。在这种情况下,对于非 2xx 错误响应将抛出以下异常:
RedirectResponseException针对 3xx 响应。ClientRequestException针对 4xx 响应。ServerResponseException针对 5xx 响应。
自定义验证
除了默认的验证行为外,你还可以使用 HttpCallValidator 插件定义自定义响应验证逻辑。这允许你验证成功 (2xx) 的响应或覆盖非 2xx 响应的处理方式。
要安装 HttpCallValidator,请在 客户端配置块 内调用 HttpResponseValidator 函数:
val client = HttpClient(CIO) {
HttpResponseValidator {
// ...
}
}验证 2xx 响应
默认验证仅对非 2xx 响应抛出异常。如果你的应用程序需要更严格的验证,可以使用 validateResponse {} 函数来验证成功的响应。
在以下示例中,服务器返回一个包含 JSON 格式错误负载的 2xx 响应。validateResponse {} 块会检查响应正文并在检测到错误时抛出自定义异常:
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:
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。
