vertx.effect.core.OauthModule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vertx-effect Show documentation
Show all versions of vertx-effect Show documentation
When actors meet Functional Programming
package vertx.effect.core;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpClientOptions;
import jsonvalues.JsObj;
import vertx.effect.Val;
import vertx.effect.exp.All;
import vertx.effect.exp.Cons;
import vertx.effect.exp.IfElse;
import vertx.effect.httpclient.*;
import vertx.effect.λ;
import vertx.effect.λc;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
public abstract class OauthModule extends HttpClientModule {
protected String accessToken;
protected BiFunction> accessTokenReq;
protected final λ readNewAccessTokenAfterRefresh;
protected final int accessTokenReqAttempts;
protected final String authorizationHeaderName;
protected final Function authorizationHeaderValue;
protected final Predicate refreshTokenPredicate;
protected final Predicate retryAccessTokenReqPredicate;
protected final Predicate retryReqPredicate;
public OauthModule(final HttpClientOptions options,
final String address,
final String authorizationHeaderName,
final Function authorizationHeaderValue,
final λ readNewAccessTokenAfterRefresh,
final Predicate refreshTokenPredicate,
final Predicate retryAccessTokenReqPredicate,
final Predicate retryReqPredicate,
final int accessTokenReqAttempts,
final int reqAttempts
) {
super(options,
address
);
this.readNewAccessTokenAfterRefresh = readNewAccessTokenAfterRefresh;
this.authorizationHeaderName = authorizationHeaderName;
this.authorizationHeaderValue = authorizationHeaderValue;
this.refreshTokenPredicate = refreshTokenPredicate;
this.retryAccessTokenReqPredicate = retryAccessTokenReqPredicate;
this.retryReqPredicate = retryReqPredicate;
this.accessTokenReqAttempts = accessTokenReqAttempts;
this.getOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.postOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.putOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.deleteOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.patchOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.headOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.connectOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.optionsOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
this.traceOauth = oauth((context, reqParams) -> httpClient.apply(reqParams.createHttpReq()),
reqAttempts,
false
);
}
public final λc getOauth;
public final λc postOauth;
public final λc putOauth;
public final λc deleteOauth;
public final λc patchOauth;
public final λc headOauth;
public final λc connectOauth;
public final λc optionsOauth;
public final λc traceOauth;
protected > λc resilientReq(final λc req,
final int reqAttempts
) {
return (context, reqParams) -> req.apply(context,
reqParams
)
.recoverWith(e ->
IfElse.predicate(All.of(retryReqPredicate.test(e),
reqAttempts > 0
)
)
.consequence(this.resilientReq(req,
reqAttempts - 1
)
.apply(reqParams)
)
.alternative(Cons.failure(e))
)
.flatMap(resp ->
IfElse.predicate(Cons.success(refreshTokenPredicate.test(resp)))
.consequence(this.oauth(req,
reqAttempts - 1,
true
)
.apply(reqParams)
)
.alternative(Cons.success(resp))
);
}
protected > λc oauth(final λc req,
final int reqAttempts,
final boolean refreshToken
) {
return (context, reqParams) ->
//really important: Cons.of instead of Cons.success to capture the state of this.accessToken
IfElse.predicate(Cons.of(()->Future.succeededFuture(refreshToken || accessToken == null)))
.consequence(
accessTokenReq.apply(context,
this
)
.flatMap(readNewAccessTokenAfterRefresh)
.retry(retryAccessTokenReqPredicate,
accessTokenReqAttempts
)
.onSuccess(newToken -> this.accessToken = newToken)
)
//really important: Cons.of instead of Cons.success to capture the state of this.accessToken
.alternative(Cons.of(()-> Future.succeededFuture(this.accessToken)))
.flatMap(token -> resilientReq(req,
reqAttempts
).apply(reqParams.setHeader(authorizationHeaderName,
authorizationHeaderValue.apply(token)
)
)
);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy