Skip to content

Commit

Permalink
feat: better serializer errors
Browse files Browse the repository at this point in the history
  • Loading branch information
realdavidvega committed Oct 11, 2024
1 parent 4d72b0d commit c2be0a6
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,47 @@ import io.ktor.http.content.*

suspend inline fun <reified A> 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"
}
}

0 comments on commit c2be0a6

Please sign in to comment.