Я выполняю HTTP-вызов с помощью Spring WebFlux WebClient (Boot 2.4.3) в Kotlin (1.4.30). Когда время ожидания запроса истекает, происходит сбой из-за исключения, но вместо этого я хотел бы вернуть значение по умолчанию. Я вижу ссылки на onError
, onStatus
и т. Д., Использованные после retrieve()
, но, похоже, они недоступны в моем случае (только body
, toEntity
, awaitExchange
)
Звонок:
suspend fun conversation(id: String): Conversation =
client.get().uri("/conversation/{id}", id).retrieve().awaitBody()
Конфигурация WebClient с таймаутами подключения и чтения:
fun webClient(url: String, connectTimeout: Int, readTimeout: Long, objectMapper: ObjectMapper): WebClient =
WebClient.builder()
.baseUrl(url)
.exchangeStrategies(
ExchangeStrategies.builder()
.codecs { configurer -> configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(objectMapper)) }
.build())
.clientConnector(
ReactorClientHttpConnector(
HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout)
.doOnConnected { connection ->
connection.addHandlerLast(ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))
}))
.build()
Модель ответа:
@JsonIgnoreProperties(ignoreUnknown = true)
data class Conversation(
val replyTimestamp: Map<String, String>,
)
Как я могу вернуть ответ по умолчанию (разговор с пустой картой) в случае тайм-аута вместо сбоя с исключением?
Обновлять:
Я попробовал предложение JArgente ниже: обновил вызов с помощью awaitExchange
и установил действительный ответ WireMock с задержкой (1010 мс), которая больше этого тайм-аута (1000 мс).
Результатом остается ReadTimeoutException, поэтому просмотр кода состояния http в этом случае не помогает.
private val defaultConversation = Conversation(emptyMap())
suspend fun conversation(id: String): Conversation =
client.get()
.uri("/conversation/{id}", id)
.awaitExchange {
response -> if (response.statusCode() == HttpStatus.OK) response.awaitBody() else defaultConversation
}
Ответ:
{
"replyTimestamp": {
"1": "2021-02-23T15:30:28.753Z",
"2": "2021-02-23T16:30:28.753Z"
}
}
Мок-конфиг для него:
{
"mappings":
[
{
"priority": 1,
"request": {
"method": "GET",
"urlPathPattern": "/conversation/1"
},
"response": {
"status": 200,
"fixedDelayMilliseconds": 1010,
"headers": {
"content-type": "application/json;charset=utf-8"
},
"bodyFileName": "conversation1.json"
}
}
]
}