com.increase.api.services.Handlers.kt Maven / Gradle / Ivy
@file:JvmName("Handlers")
package com.increase.api.services
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import com.google.common.collect.ListMultimap
import com.increase.api.core.http.BinaryResponseContent
import com.increase.api.core.http.HttpResponse
import com.increase.api.core.http.HttpResponse.Handler
import com.increase.api.errors.BadRequestException
import com.increase.api.errors.IncreaseError
import com.increase.api.errors.IncreaseException
import com.increase.api.errors.InternalServerException
import com.increase.api.errors.NotFoundException
import com.increase.api.errors.PermissionDeniedException
import com.increase.api.errors.RateLimitException
import com.increase.api.errors.UnauthorizedException
import com.increase.api.errors.UnexpectedStatusCodeException
import com.increase.api.errors.UnprocessableEntityException
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.OutputStream
internal fun emptyHandler(): Handler = EmptyHandler
private object EmptyHandler : Handler {
override fun handle(response: HttpResponse): Void? = null
}
internal fun stringHandler(): Handler = StringHandler
internal fun binaryHandler(): Handler = BinaryHandler
private object StringHandler : Handler {
override fun handle(response: HttpResponse): String {
return response.body().readBytes().toString(Charsets.UTF_8)
}
}
private object BinaryHandler : Handler {
override fun handle(response: HttpResponse): BinaryResponseContent {
return object : BinaryResponseContent {
override fun contentType(): String? =
response.headers().get("Content-Type").firstOrNull()
override fun body(): InputStream = response.body()
override fun close() = response.close()
override fun writeTo(outputStream: OutputStream) {
response.body().copyTo(outputStream)
}
}
}
}
internal inline fun jsonHandler(jsonMapper: JsonMapper): Handler {
return object : Handler {
override fun handle(response: HttpResponse): T {
try {
return jsonMapper.readValue(response.body(), jacksonTypeRef())
} catch (e: Exception) {
throw IncreaseException("Error reading response", e)
}
}
}
}
internal fun errorHandler(jsonMapper: JsonMapper): Handler {
val handler = jsonHandler(jsonMapper)
return object : Handler {
override fun handle(response: HttpResponse): IncreaseError {
try {
return handler.handle(response)
} catch (e: Exception) {
return IncreaseError.builder().build()
}
}
}
}
internal fun Handler.withErrorHandler(errorHandler: Handler): Handler {
return object : Handler {
override fun handle(response: HttpResponse): T {
when (val statusCode = response.statusCode()) {
in 200..299 -> {
return [email protected](response)
}
400 -> {
val buffered = response.buffered()
throw BadRequestException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
401 -> {
val buffered = response.buffered()
throw UnauthorizedException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
403 -> {
val buffered = response.buffered()
throw PermissionDeniedException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
404 -> {
val buffered = response.buffered()
throw NotFoundException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
422 -> {
val buffered = response.buffered()
throw UnprocessableEntityException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
429 -> {
val buffered = response.buffered()
throw RateLimitException(
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
in 500..599 -> {
val buffered = response.buffered()
throw InternalServerException(
statusCode,
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
else -> {
val buffered = response.buffered()
throw UnexpectedStatusCodeException(
statusCode,
buffered.headers(),
StringHandler.handle(buffered),
errorHandler.handle(buffered),
)
}
}
}
}
}
private fun HttpResponse.buffered(): HttpResponse {
val body = body().readBytes()
return object : HttpResponse {
override fun statusCode(): Int {
return [email protected]()
}
override fun headers(): ListMultimap {
return [email protected]()
}
override fun body(): InputStream {
return ByteArrayInputStream(body)
}
override fun close() {
[email protected]()
}
}
}