Reputation: 53
The project work with OAuth2 protocol. But there is token in request body, not in header. So I couldn't find a way send request again with new token. Flow: request -> fail -> refresh token -> request
Request exp:
{"request": "asd",
"token":"...",
"request_data":{} }
I'm sending same request with same token when error occurs, as follows:
requestExp().flatMap(resource -> {
return Single.just(new Object());
}).retryWhen(th-> {
AtomicInteger counter = new AtomicInteger();
return th.takeWhile(e -> {
if (Objects.equals(e.getMessage(), "test")) {
return counter.getAndIncrement() != 1;
}
});
});
Any help?
Upvotes: 0
Views: 573
Reputation: 400
You can try something like this:
.retryWhen {
return@retryWhen it.flatMapSingle { throwable ->
if (throwable is HttpException && throwable.code() == 401) {
// when 401 error, let's update the token and retry after that
println("Invalid token")
return@flatMapSingle refreshToken() // token source will be updated
}
// other error, no retry
return@flatMapSingle Single.error<Any>(throwable)
}
}
Example:
fun main() {
class Params(val token: String)
class Result
val tokenSource = BehaviorSubject.create<String>()
tokenSource.onNext("invalid_token")
fun request(params: Params): Single<Result> {
if (params.token != "valid_token") {
val responseBody = "".toResponseBody("application/json".toMediaTypeOrNull())
val response = retrofit2.Response.error<Any>(401, responseBody)
return Single.error(HttpException(response))
}
return Single.just(Result())
}
fun refreshToken(): Single<String> {
return Single.fromCallable {
val token = "valid_token"
tokenSource.onNext(token)
return@fromCallable token
}
}
val s = tokenSource.firstOrError() // get latest token
.flatMap { request(Params(it)) }
.retryWhen {
return@retryWhen it.flatMapSingle { throwable ->
if (throwable is HttpException && throwable.code() == 401) {
println("Invalid token")
return@flatMapSingle refreshToken() // token source will be updated
}
return@flatMapSingle Single.error<Any>(throwable)
}
}
.subscribe(
{
println("Success")
},
{
println("Error $it")
}
)
}
Upvotes: 2