/** * Copyright 2019 Coinbase, Inc. * * Licensed under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.coinbase.network.adapter import io.reactivex.BackpressureStrategy import io.reactivex.Observable import io.reactivex.functions.Function import okhttp3.ResponseBody import retrofit2.Call import retrofit2.CallAdapter import retrofit2.Converter import retrofit2.HttpException import java.io.IOException import java.lang.reflect.Type internal class KotlinRxJava2CallAdapter( private val successBodyType: Type, private val delegateAdapter: CallAdapter>, private val errorConverter: Converter, private val isFlowable: Boolean, private val isSingle: Boolean, private val isMaybe: Boolean ) : CallAdapter { override fun adapt(call: Call): Any = delegateAdapter.adapt(call) .flatMap { Observable.just>(NetworkResponse.Success(it)) } .onErrorResumeNext( Function>> { throwable -> when (throwable) { is HttpException -> { val error = throwable.response().errorBody() val errorBody = when { error == null -> null error.contentLength() == 0L -> null else -> { try { errorConverter.convert(error) } catch (e: Exception) { return@Function Observable.just( NetworkResponse.NetworkError( IOException( "Couldn't deserialize error body: ${error.string()}", e ) ) ) } } } val serverError = NetworkResponse.ServerError( errorBody, throwable.response().code() ) Observable.just(serverError) } is IOException -> { Observable.just( NetworkResponse.NetworkError( throwable ) ) } else -> { throw throwable } } }).run { when { isFlowable -> this.toFlowable(BackpressureStrategy.LATEST) isSingle -> this.singleOrError() isMaybe -> this.singleElement() else -> this } } override fun responseType(): Type = successBodyType }