Skip to content

Commit

Permalink
Throw Errors Per Operations (#290)
Browse files Browse the repository at this point in the history
PR: #290
  • Loading branch information
osama-salman99 authored Sep 5, 2023
1 parent 548832d commit 1ee8053
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,5 @@ val mustacheHelpers = mapOf(
}
}
}
},
"listApiExceptionsRanges" to {
Mustache.Lambda { fragment, writer ->
val errorCodes: MutableSet<String> = mutableSetOf()
val operationsMap: OperationsMap = fragment.context() as OperationsMap
operationsMap.operations.operation.forEach { operation ->
operation.responses.forEach { response ->
response.takeIf { !it.is2xx && !errorCodes.contains(it.code) }?.also {
writer.write("HttpStatusCodeRange(\"${it.code}\") { OpenWorldApi${it.dataType}Exception(it.status.value, fetchErrorObject(it) as ${it.dataType}) },\n")
errorCodes.add(it.code)
}
}
}
}
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ import java.util.UUID
headers.append("User-agent", userAgent)
}

override suspend fun throwServiceException(response: HttpResponse) {
throw ErrorObjectMapper.process(response)
override suspend fun throwServiceException(response: HttpResponse, operationId: String) {
throw ErrorObjectMapper.process(response, operationId)
}

{{#operation}}
Expand Down Expand Up @@ -96,7 +96,7 @@ import java.util.UUID
{{/hasFormParams}}
{{/hasBodyParam}}
}
throwIfError(response)
throwIfError(response, "{{operationId}}")
return {{^returnType}}null{{/returnType}}{{#returnType}}Response(response.body<{{{returnType}}}>(), toHeadersMap(response.headers.entries())){{/returnType}}
}
{{^isKotlin}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,31 @@ internal object DefaultHttpStatusCodeRange : HttpStatusCodeRange(
}

internal object ErrorObjectMapper {
private val httpStatusCodeRanges: List<HttpStatusCodeRange> = listOf(
private val defaultHttpStatusCodeRanges = listOf(DefaultHttpStatusCodeRange)
private val httpStatusCodeRanges: Map< String, List< HttpStatusCodeRange > > = mapOf(
{{#apiInfo}}
{{#apis}}
{{#listApiExceptionsRanges}}{{/listApiExceptionsRanges}}
{{#operations}}
{{#operation}}
Pair(
"{{operationId}}",
listOf(
{{#responses}}
{{^is2xx}}
HttpStatusCodeRange("{{code}}") { OpenWorldApi{{dataType}}Exception(it.status.value, fetchErrorObject(it) as {{dataType}}) },
{{/is2xx}}
{{/responses}}
DefaultHttpStatusCodeRange
)
){{^-last}},{{/-last}}
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
DefaultHttpStatusCodeRange
)

fun process(httpResponse: HttpResponse): OpenWorldApiException =
httpStatusCodeRanges.filter { it.matches(httpResponse.status.value.toString()) }.min().getException(httpResponse)
fun process(httpResponse: HttpResponse, operationId: String): OpenWorldApiException =
httpStatusCodeRanges.getOrDefault(operationId, defaultHttpStatusCodeRanges).filter { it.matches(httpResponse.status.value.toString()) }.min().getException(httpResponse)

private inline fun <reified T> fetchErrorObject(httpResponse: HttpResponse): T = runBlocking {
runCatching { httpResponse.body<T>() }.getOrElse { throw OpenWorldServiceException(httpResponse.bodyAsText()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ abstract class Client {
private fun isNotSuccessfulResponse(response: HttpResponse) = response.status.value !in Constant.SUCCESSFUL_STATUS_CODES_RANGE

@Suppress("unused") // This is used by the product SDKs.
suspend fun throwIfError(response: HttpResponse) {
suspend fun throwIfError(response: HttpResponse, operationId: String) {
if (isNotSuccessfulResponse(response)) {
log.info(LoggingMessageProvider.getResponseUnsuccessfulMessage(response.status))
throwServiceException(response)
throwServiceException(response, operationId)
}
}

abstract suspend fun throwServiceException(response: HttpResponse)
abstract suspend fun throwServiceException(response: HttpResponse, operationId: String)

/**
* A [Client] builder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ internal object ClientFactory {

fun createOpenWorldClient(mockEngine: MockEngine): OpenWorldClient = createOpenWorldClient(mockEngine, openWorldConfiguration)
fun createOpenWorldClient(mockEngine: HttpClientEngine, configuration: OpenWorldClientConfiguration): OpenWorldClient = object : OpenWorldClient(configuration, mockEngine) {
override suspend fun throwServiceException(response: HttpResponse) {
override suspend fun throwServiceException(response: HttpResponse, operationId: String) {
throw OpenWorldServiceException("Dummy service exception")
}
}

fun createRapidClient(mockEngine: HttpClientEngine): BaseRapidClient = object : BaseRapidClient(rapidConfiguration, mockEngine) {
override suspend fun throwServiceException(response: HttpResponse) {
override suspend fun throwServiceException(response: HttpResponse, operationId: String) {
throw OpenWorldServiceException("Dummy service exception")
}
}
Expand Down

0 comments on commit 1ee8053

Please sign in to comment.