-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Abhijit Sarkar opened SPR-15946 and commented
Actually using 5.0.0.BUILD-SNAPSHOT, forced to choose RC3 as SNAPSHOT isn't available in the list.
With the latest SNAPSHOT, the WebClient.retrieve behavior has changed such that if the response has status code 4xx or 5xx, it returns a successful Mono<? extends Throwable> instead of a Mono with error. This makes no sense and completely breaks the client code. Because the ResponseSpec has no isSuccessful method or something along that line, the client is completely unaware that the Mono now contains a Throwable, and gets a ClassCastException as follows:
java.lang.ClassCastException: org.springframework.web.reactive.function.client.WebClientResponseException cannot be cast to java.lang.String
The expected behavior would be that the ResponseSpec.onStatus method return an error Mono, or the various bodyTo* methods would handle this complication. It is simply not the client's problem.
Here's an alternative implementation that solves this problem; it's in Kotlin but the error handling is lifted straight from DefaultWebClient:
fun ClientResponse.isError(): Boolean = this.statusCode().is4xxClientError || this.statusCode().is5xxServerError
private inline fun <reified T> ClientResponse.toMono(): Mono<T> {
return if (this.isError()) {
this.body(BodyExtractors.toDataBuffers())
.reduce { obj, buffers -> obj.write(buffers) }
.map { dataBuffer ->
dataBuffer.readableByteCount()
.let { ByteArray(it) }
.also { dataBuffer.read(it) }
.apply { DataBufferUtils.release(dataBuffer) }
}
.map { bodyBytes ->
val msg = "${this.statusCode().value()} ${this.statusCode().reasonPhrase}"
val charset = this.headers().contentType()
.map { it.charset }
.orElse(StandardCharsets.UTF_8)
WebClientResponseException(
msg,
this.statusCode().value(),
this.statusCode().reasonPhrase,
this.headers().asHttpHeaders(),
bodyBytes,
charset
)
}
.flatMap { Mono.error<T>(it) }
} else {
this.bodyToMono(T::class.java)
}
}
Affects: 5.0 RC3
Attachments:
- spr-15946.zip (76.26 kB)
- spr-15946-reopen.zip (78.95 kB)