diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerError.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerError.kt index c55a8e3aa..b21cdb257 100644 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerError.kt +++ b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerError.kt @@ -1,4 +1,16 @@ package com.xebia.functional.openai.errors -class ResponseSerializerError(message: String, cause: Throwable? = null) : - Exception(message, cause) +data class ResponseSerializerError( + override val message: String, + override val cause: Throwable?, + val info: ResponseErrorInfo, +) : Exception(message, cause) + +data class ResponseErrorInfo( + val requestUrl: String, + val requestMethod: String, + val requestBody: String, + val responseStatus: Int, + val responseHeaders: String, + val responseBody: String +) diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerErrors.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerErrors.kt index 4fafce148..0133f71d5 100644 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerErrors.kt +++ b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/errors/ResponseSerializerErrors.kt @@ -6,28 +6,47 @@ import io.ktor.http.content.* suspend inline fun HttpResponse.serializeOrThrowWithResponseInfo(): A = try { - this.body() ?: throw ResponseSerializerError("Response body is null") + this.body() ?: throwResponseSerializerError(title = "Response body is null") } catch (e: Exception) { - val requestBody = - when (val content = this.request.content) { - is OutgoingContent.ByteArrayContent -> content.bytes().decodeToString() - is OutgoingContent.NoContent -> "NoContent" - is OutgoingContent.ProtocolUpgrade -> "ProtocolUpgrade" - is OutgoingContent.ReadChannelContent -> "ReadChannelContent" - is OutgoingContent.WriteChannelContent -> "WriteChannelContent" - else -> "UnknownContent" - } - throw ResponseSerializerError( - """ - |Failed to serialize response body to ${A::class.simpleName} - |Request URL: ${this.request.url} - |Request Method: ${this.request.method} - |Request Body: $requestBody - |Response Status: ${this.status} - |Response Headers: ${this.headers} - |Response Body: ${this.bodyAsText()} - """ - .trimMargin(), - e + throwResponseSerializerError( + title = "Failed to serialize response body to ${A::class.simpleName}", + cause = e ) } + +suspend fun HttpResponse.throwResponseSerializerError( + title: String, + cause: Throwable? = null +): Nothing { + val errorInfo = ResponseErrorInfo( + requestUrl = this.request.url.toString(), + requestMethod = this.request.method.value, + requestBody = extractRequestBody(this), + responseStatus = this.status.value, + responseHeaders = this.headers.toString(), + responseBody = this.bodyAsText() + ) + + val message = """ + |$title + |Request URL: ${errorInfo.requestUrl} + |Request Method: ${errorInfo.requestMethod} + |Request Body: ${errorInfo.requestBody} + |Response Status: ${errorInfo.responseStatus} + |Response Headers: ${errorInfo.responseHeaders} + |Response Body: ${errorInfo.responseBody} + """.trimMargin() + + throw ResponseSerializerError(message, cause, errorInfo) +} + +private fun extractRequestBody(response: HttpResponse): String { + return when (val content = response.request.content) { + is OutgoingContent.ByteArrayContent -> content.bytes().decodeToString() + is OutgoingContent.NoContent -> "NoContent" + is OutgoingContent.ProtocolUpgrade -> "ProtocolUpgrade" + is OutgoingContent.ReadChannelContent -> "ReadChannelContent" + is OutgoingContent.WriteChannelContent -> "WriteChannelContent" + else -> "UnknownContent" + } +}