/* * This file is part of GNU Taler * (C) 2020 Taler Systems S.A. * * GNU Taler is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation; either version 3, or (at your option) any later version. * * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * GNU Taler; see the file COPYING. If not, see */ package net.taler.merchantlib import io.ktor.client.call.receive import io.ktor.client.features.ClientRequestException import io.ktor.client.features.ResponseException import io.ktor.client.features.ServerResponseException import kotlinx.serialization.Serializable class Response private constructor( private val value: Any? ) { companion object { suspend fun response(request: suspend () -> T): Response { return try { success(request()) } catch (e: Throwable) { println(e) failure(e) } } fun success(value: T): Response = Response(value) fun failure(e: Throwable): Response = Response(Failure(e)) } val isFailure: Boolean get() = value is Failure suspend fun handle(onFailure: ((String) -> Any)? = null, onSuccess: ((T) -> Any)? = null) { if (value is Failure) onFailure?.let { it(getFailureString(value)) } else onSuccess?.let { @Suppress("UNCHECKED_CAST") it(value as T) } } suspend fun handleSuspend( onFailure: ((String) -> Any)? = null, onSuccess: (suspend (T) -> Any)? = null ) { if (value is Failure) onFailure?.let { it(getFailureString(value)) } else onSuccess?.let { @Suppress("UNCHECKED_CAST") it(value as T) } } private suspend fun getFailureString(failure: Failure): String = when (failure.exception) { is ClientRequestException -> getExceptionString(failure.exception) is ServerResponseException -> getExceptionString(failure.exception) else -> failure.exception.toString() } private suspend fun getExceptionString(e: ResponseException): String { return try { val error: Error = e.response.receive() "Error ${error.code}: ${error.hint}" } catch (ex: Exception) { "Status code: ${e.response.status.value}" } } private class Failure(val exception: Throwable) @Serializable private class Error( val code: Int?, val hint: String? ) }