catch non-IOExceptions in Retrofit interceptors

This commit is contained in:
johan12345
2026-05-30 17:07:45 +02:00
parent b7571acc9e
commit b57bb5d884
7 changed files with 33 additions and 10 deletions

View File

@@ -2,10 +2,27 @@ package net.vonforst.evmap.api
import okhttp3.Interceptor
import okhttp3.Response
import okio.IOException
import retrofit2.HttpException
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlin.time.TimeSource
fun Interceptor.Chain.proceedSafely(request: okhttp3.Request): Response {
return try {
proceed(request)
} catch (e: Throwable) {
if (e is IOException) {
throw e
} else if (e is HttpException) {
// wrap HttpExceptions as IOExceptions, so that they are properly handled by Retrofit's error handling
throw IOException("${e.response()}", e)
} else {
// wrap other exceptions as IOExceptions, so that they are properly handled by Retrofit's error handling
throw IOException(e)
}
}
}
class RateLimitInterceptor : Interceptor {
private val rateLimiter = SimpleRateLimiter(3.0)
@@ -16,7 +33,7 @@ class RateLimitInterceptor : Interceptor {
// limit requests sent to NewMotion to 3 per second
rateLimiter.acquire()
var response: Response = chain.proceed(request)
var response: Response = chain.proceedSafely(request)
// 403 is how the NewMotion API indicates a rate limit error
if (!response.isSuccessful && response.code == 403) {
response.close()
@@ -25,11 +42,11 @@ class RateLimitInterceptor : Interceptor {
Thread.sleep(1000)
} catch (e: InterruptedException) {
}
response = chain.proceed(request)
response = chain.proceedSafely(request)
}
return response
} else {
return chain.proceed(request)
return chain.proceedSafely(request)
}
}
}

View File

@@ -4,6 +4,7 @@ import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import net.vonforst.evmap.api.proceedSafely
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.Chargepoint
import net.vonforst.evmap.utils.distanceBetween
@@ -91,7 +92,7 @@ interface EnBwApi {
.header("Referer", "https://www.enbw.com/")
.header("Accept", "application/json")
.build()
chain.proceed(request)
chain.proceedSafely(request)
}.build()
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl ?: "https://enbw-emp.azure-api.net/emobility-public-api/api/v1/")

View File

@@ -3,6 +3,7 @@ package net.vonforst.evmap.api.availability.tesla
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import net.vonforst.evmap.api.proceedSafely
import okhttp3.CacheControl
import okhttp3.OkHttpClient
import retrofit2.Retrofit
@@ -48,7 +49,7 @@ interface TeslaCuaApi {
val request = chain.request().newBuilder()
.cacheControl(CacheControl.Builder().maxStale(24, TimeUnit.HOURS).build())
.build()
chain.proceed(request)
chain.proceedSafely(request)
}.build()
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl ?: "https://www.tesla.com/cua-api/")

View File

@@ -7,6 +7,7 @@ import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import kotlinx.coroutines.runBlocking
import net.vonforst.evmap.api.proceedSafely
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
@@ -135,7 +136,7 @@ interface TeslaOwnerApi {
.header("x-tesla-user-agent", "TeslaApp/4.44.5-3304/3a5d531cc3/android/27")
.header("Accept", "*/*")
.build()
chain.proceed(request)
chain.proceedSafely(request)
}.build()
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl ?: "https://owner-api.teslamotors.com")
@@ -376,7 +377,7 @@ interface TeslaChargingOwnershipGraphQlApi {
.header("x-tesla-user-agent", "TeslaApp/4.44.5-3304/3a5d531cc3/android/27")
.header("Accept", "*/*")
.build()
chain.proceed(request)
chain.proceedSafely(request)
}.build()
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl ?: "https://akamai-apigateway-charging-ownership.tesla.com")

View File

@@ -4,6 +4,7 @@ import android.content.Context
import com.squareup.moshi.Moshi
import net.vonforst.evmap.BuildConfig
import net.vonforst.evmap.addDebugInterceptors
import net.vonforst.evmap.api.proceedSafely
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.Chargepoint
import okhttp3.Cache
@@ -46,7 +47,7 @@ private interface FronyxApiRetrofit {
.header("X-API-Token", apikey)
.header("Content-Type", "application/json")
.build()
chain.proceed(new)
chain.proceedSafely(new)
}
if (BuildConfig.DEBUG) {
addDebugInterceptors()

View File

@@ -21,6 +21,7 @@ import net.vonforst.evmap.api.mapPower
import net.vonforst.evmap.api.mapPowerInverse
import net.vonforst.evmap.api.nameForPlugType
import net.vonforst.evmap.api.powerSteps
import net.vonforst.evmap.api.proceedSafely
import net.vonforst.evmap.model.BooleanFilter
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.Chargepoint
@@ -131,7 +132,7 @@ interface GoingElectricApi {
var original = chain.request()
val url = original.url.newBuilder().addQueryParameter("key", apikey).build()
original = original.newBuilder().url(url).build()
chain.proceed(original)
chain.proceedSafely(original)
}
if (BuildConfig.DEBUG) {
addDebugInterceptors()

View File

@@ -16,6 +16,7 @@ import net.vonforst.evmap.api.StringProvider
import net.vonforst.evmap.api.mapPower
import net.vonforst.evmap.api.mapPowerInverse
import net.vonforst.evmap.api.powerSteps
import net.vonforst.evmap.api.proceedSafely
import net.vonforst.evmap.model.BooleanFilter
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.ChargepointListItem
@@ -101,7 +102,7 @@ interface OpenChargeMapApi {
val new = original.newBuilder()
.header("X-API-Key", apikey)
.build()
chain.proceed(new)
chain.proceedSafely(new)
}
if (BuildConfig.DEBUG) {
addDebugInterceptors()