我们有一台服务器来检索OAUTH令牌,并通过WebClient.filter方法将oauth令牌添加到每个请求中 e.g
webClient.post()
.uri(properties.getServiceRequestUrl())
.contentType(MediaType.APPLICATION_JSON)
.body(fromObject(createRequest))
.retrieve()
.bodyToMono(MyResponseObject.class)
.retryWhen(retryOnceOn401(provider))
private Retry<Object> retryOnceOn401(TokenProvider tokenProvider) {
return Retry.onlyIf(context -> context.exception() instanceof WebClientResponseException && ((WebClientResponseException) context.exception()).getStatusCode() == HttpStatus.UNAUTHORIZED)
.doOnRetry(objectRetryContext -> tokenProvider.invalidate());
}
我想要一个重试功能,在401错误时,将使令牌无效并再次尝试请求 我有这样的工作
.filter(((request, next) -> next.exchange(request).retryWhen(retryOnceOn401(tokenProvider))))
有没有办法将它移到webClient.mutate()..... build()函数? 以便所有请求都有这个重试工具?
我尝试添加过滤器,但它似乎不起作用。
FROM python:3.5
有关最佳方法的任何建议吗? 此致
答案 0 :(得分:5)
我想到了这一点,在看到重试只对异常有效后很明显,webClient不会抛出异常,因为clientResponse对象只保存响应,只有当调用bodyTo时才会在http状态上抛出异常,所以要解决这个问题,可以模仿这种行为
@Bean(name = "retryWebClient")
public WebClient retryWebClient(WebClient.Builder builder, TokenProvider tokenProvider) {
return builder.baseUrl("http://localhost:8080")
.filter((request, next) ->
next.exchange(request)
.doOnNext(clientResponse -> {
if (clientResponse.statusCode() == HttpStatus.UNAUTHORIZED) {
throw new RuntimeException();
}
}).retryWhen(Retry.anyOf(RuntimeException.class)
.doOnRetry(objectRetryContext -> tokenProvider.expire())
.retryOnce())
).build();
}
使用重复/重试编辑其中一个功能是,它不会更改原始请求,在我的情况下,我需要检索新的OAuth令牌,但上面发送了相同(已过期)令牌。 我确实想办法使用交换过滤器,一旦OAuth密码流在spring-security-2.0中,我应该可以将它与AccessTokens等集成,但同时
ExchangeFilterFunction retryOn401Function(TokenProvider tokenProvider) {
return (request, next) -> next.exchange(request)
.flatMap((Function<ClientResponse, Mono<ClientResponse>>) clientResponse -> {
if (clientResponse.statusCode().value() == 401) {
ClientRequest retryRequest = ClientRequest.from(request).header("Authorisation", "Bearer " + tokenProvider.getNewToken().toString()).build();
return next.exchange(retryRequest);
} else {
return Mono.just(clientResponse);
}
});
}