From 74832b840b967dabbf7074580ce4684289519cf5 Mon Sep 17 00:00:00 2001 From: Peter Vacho Date: Sat, 11 Jan 2025 18:37:51 +0100 Subject: [PATCH] feat: Handle ngrok proxy --- app/build.gradle.kts | 1 + .../neat_calendar/GlobalExceptionHandler.kt | 40 ++++++++++++++++++- .../activities/ApiUnreachableActivity.kt | 18 +++++++++ .../neat_calendar/api/RetrofitClient.kt | 16 +++++++- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7cd651c..1b678c3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -25,6 +25,7 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) + signingConfig = signingConfigs.getByName("debug") } } compileOptions { diff --git a/app/src/main/java/com/p_vacho/neat_calendar/GlobalExceptionHandler.kt b/app/src/main/java/com/p_vacho/neat_calendar/GlobalExceptionHandler.kt index c5f59ac..684b882 100644 --- a/app/src/main/java/com/p_vacho/neat_calendar/GlobalExceptionHandler.kt +++ b/app/src/main/java/com/p_vacho/neat_calendar/GlobalExceptionHandler.kt @@ -18,8 +18,28 @@ class GlobalExceptionHandler( private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler() override fun uncaughtException(t: Thread, e: Throwable) { + if (e is IllegalStateException) { + if (e.message?.startsWith("Unexpected response from ping: ") != true) throw e + + Log.e("GlobalExceptionHandler", "Got IllegalStateException for unexpected ping response") + + val msg = e.message!!.removePrefix("Unexpected response from ping: ") + if (msg.startsWith("exc - ")) { + val exc = msg.removePrefix("exc - ") + val exception = ExceptionSerializer.deserialize(exc) + Log.e("GlobalExceptionHandler", "Deserialized HTTP Exception") + Log.e("GlobalExceptionHandler", "Exception Type: ${exception.type}") + Log.e("GlobalExceptionHandler", "Message: ${exception.message}") + } else { + Log.e("GlobalExceptionHandler", "Exc:", e) + } + + navigateToApiUnreachableActivity() + return + } + if (e !is HttpException) { - Log.e("GlobalExceptionHandler", "Propgating unhandled exception", e) + Log.e("GlobalExceptionHandler", "Propagating unhandled exception", e) defaultHandler?.uncaughtException(t, e) return } @@ -58,7 +78,23 @@ class GlobalExceptionHandler( return } - Log.e("GlobalExceptionHandler", "Propgating unhandled exception", e) + // ngrok + if (e.code() == 400) { + val errorBody = e.response()?.errorBody()?.string() + if (errorBody != null) { + val containsNgrokMeta = errorBody.contains("""""") + val containsNgrokMessage = errorBody.contains("Traffic was successfully tunneled") + + if (containsNgrokMeta && containsNgrokMessage) { + Log.e("GlobalExceptionHandler", "Caught ngrok API Unreachable HTML Response") + navigateToApiUnreachableActivity() + return + } + } + // fall through + } + + Log.e("GlobalExceptionHandler", "Propagating unhandled exception", e) defaultHandler?.uncaughtException(t, e) return } diff --git a/app/src/main/java/com/p_vacho/neat_calendar/activities/ApiUnreachableActivity.kt b/app/src/main/java/com/p_vacho/neat_calendar/activities/ApiUnreachableActivity.kt index f17b131..f41dcf7 100644 --- a/app/src/main/java/com/p_vacho/neat_calendar/activities/ApiUnreachableActivity.kt +++ b/app/src/main/java/com/p_vacho/neat_calendar/activities/ApiUnreachableActivity.kt @@ -144,6 +144,24 @@ class ApiUnreachableActivity : AppCompatActivity() { Log.e("API_REACHABILITY", "Stacktrace: ${it.stacktrace.joinToString("\n")}") } + false + } catch (e: IllegalStateException) { + if (e.message?.startsWith("Unexpected response from ping") != true) throw e + + val msg = e.message!!.removePrefix("Unexpected response from ping: ") + if (msg.startsWith("exc - ")) { + exception = ExceptionSerializer.deserialize(msg.removePrefix("exc - ")) + } else { + // This is a bit hacky, but we need a SerializedException to store here + val exc = ExceptionSerializer.serialize(e) + exception = ExceptionSerializer.deserialize(exc) + } + + exception!!.let { + Log.e("API_REACHABILITY", "Exception: ${it.type}") + Log.e("API_REACHABILITY", "Message: ${it.message}") + Log.e("API_REACHABILITY", "Stacktrace: ${it.stacktrace.joinToString("\n")}") + } false } } diff --git a/app/src/main/java/com/p_vacho/neat_calendar/api/RetrofitClient.kt b/app/src/main/java/com/p_vacho/neat_calendar/api/RetrofitClient.kt index c9de5be..dec7c16 100644 --- a/app/src/main/java/com/p_vacho/neat_calendar/api/RetrofitClient.kt +++ b/app/src/main/java/com/p_vacho/neat_calendar/api/RetrofitClient.kt @@ -18,6 +18,9 @@ import com.p_vacho.neat_calendar.api.services.EventsService import com.p_vacho.neat_calendar.api.services.InvitationsService import com.p_vacho.neat_calendar.api.services.NotificationService import com.p_vacho.neat_calendar.api.services.UsersService +import com.p_vacho.neat_calendar.util.ExceptionSerializer +import okhttp3.ResponseBody +import retrofit2.HttpException object RetrofitClient { private const val DEFAULT_BASE_URL = "http://10.0.2.2:8000" @@ -115,8 +118,17 @@ object RetrofitClient { * If the API isn't reachable, this will throw HttpException with code 503. */ suspend fun ping() { - // This will potentially raise 503 HttpException - val responseBody = retrofitClient.create(GeneralService::class.java).ping() + val responseBody: ResponseBody + try { + responseBody = retrofitClient.create(GeneralService::class.java).ping() + } catch (e: HttpException) { + // Unreachable + if (e.code() == 503) throw e + + // Anything else: + val exc = ExceptionSerializer.serialize(e) + throw IllegalStateException("Unexpected response from ping: exc - $exc") + } val responseText = responseBody.string()