Android 改装及保养;RxJava2刷新令牌并重试
我有一个登录端点,通过它我可以接收authToken和refreshToken。第一个将在一小时后过期,因此我应该使用第二个来刷新它并继续应用程序流 现在,我的应用程序到处都是改装呼叫,我可能在任何给定时刻都会收到Android 改装及保养;RxJava2刷新令牌并重试,android,kotlin,rx-java2,Android,Kotlin,Rx Java2,我有一个登录端点,通过它我可以接收authToken和refreshToken。第一个将在一小时后过期,因此我应该使用第二个来刷新它并继续应用程序流 现在,我的应用程序到处都是改装呼叫,我可能在任何给定时刻都会收到401,那么我如何才能在每次收到401时都发出刷新令牌,然后重试原始请求 这是我的刷新签名: @POST("/auth/actions/refresh") fun refreshToken(@Body tokenRefresh: TokenRefresh): Single&l
401
,那么我如何才能在每次收到401
时都发出刷新令牌,然后重试原始请求
这是我的刷新签名:
@POST("/auth/actions/refresh")
fun refreshToken(@Body tokenRefresh: TokenRefresh): Single<LoginResponse>
fun reauthenticate(): Single<AnyAuthResponse>
@POST(“/auth/actions/refresh”)
fun refreshToken(@Body tokenRefresh:tokenRefresh):单个
我考虑用一个方法withAuth()
创建一个基本存储库类,该方法将任何可观察的/单个/可流动的
,然后应用这个逻辑,但我找不到实现它的方法
看到了很多实现,但没有一个符合我的需要。。。有人能把我推向正确的方向吗
但是,我发现flatmapping上似乎有一些错误,我只是遇到了类似的需求,并提出了以下解决方案。它非常简单,只需尝试调用REST端点一次,如果使用HTTP 401调用失败,它将重新验证并再次重复调用。否则它只会发出原始错误
fun <T> Single<T>.withAuth() = retryWhen { errors ->
var firstAttempt = true
errors.flatMapSingle { error ->
if (firstAttempt && error is HttpException && error.code() == 401) {
firstAttempt = false
reauthenticate()
} else {
Single.error(it)
}
}
}
fun Single.withAuth()=retryWhen{errors->
var firsttrunt=true
errors.flatMapSingle{error->
if(firsttrunt&&error为HttpException&&error.code()==401){
首次尝试=错误
重新验证()
}否则{
单一错误(it)
}
}
}
其中,重新验证功能具有以下签名:
@POST("/auth/actions/refresh")
fun refreshToken(@Body tokenRefresh: TokenRefresh): Single<LoginResponse>
fun reauthenticate(): Single<AnyAuthResponse>
fun重新验证():单一
请注意,具体的异常类型可能取决于您实际使用的HTTP实现,因此您可能希望更新条件以检测HTTP 401响应,但代码应该为您提供解决问题的总体方案。我认为您可以在不修改所有调用的情况下完成此操作。在改装中添加一个验证器
您可以使用Interceptor拦截每个请求,并检查它是否返回401
-未经授权的访问和iff,然后刷新令牌并重播当前API请求
public final class SessionInterceptor implements Interceptor {
// gets intercept
@Override public Response intercept(@NonNull final Chain chain) throws IOException {
final Request request = chain.request();
final Response response = chain.proceed(request);
final ResponseBody responseBody = response.body();
if (response.code() == 401) {
synchronized (this) {
// Refresh your token
// Update your authToken + Refreshed token
final retrofit2.Response response = refreshToken();
}
}
// Replay the original request
// Perform request, here original request will be executed
final Request original = chain.request();
final Request.Builder builder = original.newBuilder();
// Set your new refreshed token
if (accessToken.isSet()) {
builder.header(AUTHORIZATION, String.format(BEARER,
accessToken.get()));
}
final Request request = builder.method(original.method(), original.body()).build();
return chain.proceed(request);
}
}