Add biometric lock and rate limit handling
Biometric lock: opt-in Face ID/Touch ID/fingerprint app lock with toggle in ProfileScreen. Locks on background, requires auth on foreground return. Platform implementations: BiometricPrompt (Android), LAContext (iOS). Rate limit: 429 responses parsed with Retry-After header, user-friendly error messages in all 10 locales, retry plugin respects 429. ErrorMessageParser updated for both iOS Swift and KMM.
This commit is contained in:
@@ -52,11 +52,12 @@ fun HttpClientConfig<*>.installCommonPlugins() {
|
||||
gzip()
|
||||
}
|
||||
|
||||
// Task 2: Retry with exponential backoff for server errors and IO exceptions
|
||||
// Task 2: Retry with exponential backoff for server errors, IO exceptions,
|
||||
// and 429 rate-limit responses (using the Retry-After header for delay).
|
||||
install(HttpRequestRetry) {
|
||||
maxRetries = 3
|
||||
retryIf { _, response ->
|
||||
response.status.value in 500..599
|
||||
response.status.value in 500..599 || response.status.value == 429
|
||||
}
|
||||
retryOnExceptionIf { _, cause ->
|
||||
// Retry on network-level IO errors (connection resets, timeouts, etc.)
|
||||
@@ -67,8 +68,8 @@ fun HttpClientConfig<*>.installCommonPlugins() {
|
||||
cause is kotlinx.io.IOException
|
||||
}
|
||||
exponentialDelay(
|
||||
base = 1000.0, // 1 second base
|
||||
maxDelayMs = 10000 // 10 second max
|
||||
base = 1000.0,
|
||||
maxDelayMs = 10_000
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,19 @@ object ErrorParser {
|
||||
* Parses error response from the backend.
|
||||
* The backend returns: {"error": "message"}
|
||||
* Falls back to detail field or field-specific errors if present.
|
||||
* For 429 responses, includes the Retry-After value in the message.
|
||||
*/
|
||||
suspend fun parseError(response: HttpResponse): String {
|
||||
// Handle 429 rate-limit responses with Retry-After header
|
||||
if (response.status.value == 429) {
|
||||
val retryAfter = response.headers["Retry-After"]?.toLongOrNull()
|
||||
return if (retryAfter != null) {
|
||||
"Too many requests. Please try again in $retryAfter seconds."
|
||||
} else {
|
||||
"Too many requests. Please try again later."
|
||||
}
|
||||
}
|
||||
|
||||
return try {
|
||||
val errorResponse = response.body<ErrorResponse>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user