problem-details-ktor-client
Ktor Client integration: turn a recognized application/problem+json error response into the same io.github.ilyankin.rfc9457.ProblemException that application code throws on the server side and problem-details-ktor answers.
This module never depends on problem-details-ktor. It only needs to know the wire format, not how the other side of the connection is built — the same reasoning that keeps problem-details-ktor itself independent of either XML module.
JSON only, likewise by artifact: the Appendix B XML form is decoded by problemXml() in problem-details-ktor-client-xml, so a client that never speaks XML never resolves an XML parser. Registering both is order-independent — each gates on a Content-Type the other never matches — unlike the server's ContentNegotiation pair, where order decides an absent or wildcard Accept.
expectSuccess must be true
Ktor's own HttpClientConfig.expectSuccess defaults to false. Without it, nothing throws for a non-2xx response in the first place, so there is nothing for this module to intercept and replace:
val client = HttpClient(CIO) {
expectSuccess = true
HttpResponseValidator {
problemJson()
}
}A client that has to keep the default can opt in per request instead — client.get(url) { expectSuccess = true }. Either way, the failure mode when it is missing is silence: nothing throws, and get() returns the error response as if it were a normal one.
What it does not do
It does not touch outgoing requests — no automatic Accept: application/problem+json header. Ktor's own default response validation runs regardless of what Accept was sent, and a server may answer with a problem document even when the client did not list the media type in Accept: RFC 9457 §3 does exactly that in its own example, as RFC 9110 §12.5.1 allows.