libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 9eb38df871680da503e2ddba8560dd1736829671
parent ce74df3f515cc5caec39381c00645714f3d7f5ba
Author: MS <ms@taler.net>
Date:   Sat, 31 Dec 2022 09:40:14 +0100

Bad request handling for JSON.

Get the root cause and include it into the response.

Diffstat:
Msandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt | 2+-
Msandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt | 20++++++++++++--------
Msandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt | 6+++---
3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt @@ -137,7 +137,7 @@ suspend fun respondEbicsTransfer( * to an invalid request. Recall: Sandbox is multi-host, and * which Ebics host was requested belongs to the request document. * - * Therefore, because any (? Please verify!) Ebics response + * Therefore, because any Ebics response * should speak for one Ebics host, we can't respond any Ebics * type when the Ebics host ID remains unknown due to invalid * request. Instead, we'll respond plain text: diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/Main.kt @@ -491,7 +491,6 @@ val sandboxApp: Application.() -> Unit = { } install(IgnoreTrailingSlash) install(ContentNegotiation) { - register(ContentType.Text.Xml, XMLEbicsConverter()) /** * Content type "text" must go to the XML parser @@ -548,9 +547,12 @@ val sandboxApp: Application.() -> Unit = { } // Happens when a request fails to parse. exception<BadRequestException> { call, wrapper -> - var errorMessage: String? = wrapper.message // default, if no further details can be found. + var rootCause = wrapper.cause + while (rootCause?.cause != null) rootCause = rootCause.cause + val errorMessage: String? = rootCause?.message ?: wrapper.message if (errorMessage == null) { logger.error("The bank didn't detect the cause of a bad request, fail.") + logger.error(wrapper.stackTraceToString()) throw SandboxError( HttpStatusCode.InternalServerError, "Did not find bad request details." @@ -1052,9 +1054,8 @@ val sandboxApp: Application.() -> Unit = { } /** * The catch blocks try to extract a EBICS error message from the - * exception type being handled. NOT (double) logging under each - * catch block as ultimately the registered exception handler is expected - * to log. */ + * exception type being handled. NOT logging under each catch block + * as ultimately the registered exception handler is expected to log. */ catch (e: UtilError) { throw EbicsProcessingError("Serving EBICS threw unmanaged UtilError: ${e.reason}") } @@ -1065,15 +1066,18 @@ val sandboxApp: Application.() -> Unit = { when (e.errorCode) { LibeufinErrorCode.LIBEUFIN_EC_INVALID_STATE -> throw EbicsProcessingError("Invalid bank state.") LibeufinErrorCode.LIBEUFIN_EC_INCONSISTENT_STATE -> throw EbicsProcessingError("Inconsistent bank state.") - else -> throw EbicsProcessingError("Unknown LibEuFin error code: ${e.errorCode}.") + else -> throw EbicsProcessingError("Unknown Libeufin error code: ${e.errorCode}.") } } catch (e: EbicsNoDownloadDataAvailable) { respondEbicsTransfer(call, e.errorText, e.errorCode) } catch (e: EbicsRequestError) { - // Preventing the last catch-all block - // from capturing a known type. + /** + * Preventing the last catch-all block from handling + * a known error type. Rethrowing here to let the top-level + * handler take action. + */ throw e } catch (e: Exception) { diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt b/sandbox/src/main/kotlin/tech/libeufin/sandbox/XMLEbicsConverter.kt @@ -13,10 +13,10 @@ import tech.libeufin.util.XMLUtil class XMLEbicsConverter : ContentConverter { override suspend fun deserialize( - charset: io.ktor.utils.io.charsets.Charset, - typeInfo: io.ktor.util.reflect.TypeInfo, + charset: Charset, + typeInfo: TypeInfo, content: ByteReadChannel - ): Any? { + ): Any { return withContext(Dispatchers.IO) { try { receiveEbicsXmlInternal(content.toInputStream().reader().readText())