我在REST API中具有以下端点:
public interface AutomoticzAPI {
@POST("/api/beacon_auth/login")
Single<LoginResponse> login(@Body LoginRequest request);
@GET("/api/system/ws_devices")
Single<WSDevicesResponse> wsDeviceList(@Header("Authorization") String tokenHeader);
}
当我调用login
端点时,作为响应,我收到了保存到ClientSession
持有人对象中的访问令牌。稍后,我可以从ClientSession
检索令牌来调用服务器的受保护资源:
api.login(ClientSession.getInstance().getLoginRequest(login, password))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(loginResponse -> {
String accessToken = loginResponse.getAccessToken();
ClientSession.getInstance().setAccessToken(accessToken);
view.onLoginSuccess();
}, throwable -> {
RetrofitException exception = (RetrofitException) throwable;
if (exception.getKind().equals(RetrofitException.Kind.HTTP)){
view.onLoginFailed(exception.getMessage());
} else if(exception.getKind().equals(RetrofitException.Kind.NETWORK))
{
view.onLoginFailed("Network error...");
} else {
view.onLoginFailed("Unknown error occurred...");
}
});
当我调用wsDeviceList
端点时,服务器可能返回401 HTTP响应代码和json正文以及错误代码和消息:
{
"code": "EXPIRED-TOKEN",
"message": "Token expired"
}
如果发生这种情况,我想再次调用登录端点以获取新的访问令牌。到目前为止,这是我的代码:
ClientSession clientSession = ClientSession.getInstance();
String token = "Bearer "+clientSession.getAccessToken();
String url = ClientSession.getInstance().getUrl();
AutomoticzAPI api = NetworkManager.getApiClient(url);
api.wsDeviceList(token)
.retryWhen(throwableFlowable -> throwableFlowable.flatMap(
new Function<Throwable, Publisher<?>>() {
@Override
public Publisher<?> apply(Throwable throwable) throws Exception {
RetrofitException exception = (RetrofitException) throwable;
if (exception.isUnauthorizedError()){
return relogin(api, clientSession.getLoginRequest());
}
return (Publisher<?>) throwable;
}
}
))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(wsDevicesResponse -> {
view.onDeviceListLoaded(wsDevicesResponse.getWsdevices());
}, throwable -> {
RetrofitException exception = (RetrofitException) throwable;
view.onError(exception);
});
}
public Publisher<?> relogin(AutomoticzAPI api, LoginRequest loginRequest){
return (Publisher<?>) api.login(loginRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(loginResponse -> {
String accessToken = loginResponse.getAccessToken();
ClientSession.getInstance().setAccessToken(accessToken);
}, throwable -> {
RetrofitException exception = (RetrofitException) throwable;
view.onError(exception);
});
}
但是当执行relogin
方法时,我的程序崩溃了。
我不精通RxJava,可能做错了。如何使召回login
刷新访问令牌,然后再次调用wsDeviceList
?
答案 0 :(得分:1)
使用翻新的Authenticator API并在此调用访问令牌api内获取访问令牌,然后使用此访问令牌重试失败的API。