添加重试WebClient的所有请求 [英] Adding a retry all requests of WebClient

查看:40
本文介绍了添加重试WebClient的所有请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个服务器来检索 OAUTH 令牌,并且通过 WebClient.filter 方法将 oauth 令牌添加到每个请求中例如

we have a server to retrieve a OAUTH token, and the oauth token is added to each request via WebClient.filter method e.g

webClient
                .mutate()
                .filter((request, next) -> tokenProvider.getBearerToken()
                        .map(token -> ClientRequest.from(request)
                                .headers(httpHeaders -> httpHeaders.set("Bearer", token))
                                .build()).flatMap(next::exchange))
                .build();
TokenProvider.getBearerToken returns Mono<String> since it is a webclient request (this is cached)

我想要一个重试功能,在 401 错误时,将使令牌无效并再次尝试请求我有这样的工作

I want to have a retry functionality that on 401 error, will invalidate the token and try the request again I have this working like so

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());
    }

有没有办法将其移动到 webClient.mutate().....build() 函数?以便所有请求都具有此重试功能?

is there a way to move this up to the webClient.mutate().....build() function? so that all requests will have this retry facility?

我尝试添加为过滤器,但它似乎不起作用,例如

I tried adding as a filter but it didn't seem to work e.g.

.filter(((request, next) -> next.exchange(request).retryWhen(retryOnceOn401(tokenProvider))))

对解决此问题的最佳方法有什么建议吗?问候

any suggestions of the best way to approach this? Regards

推荐答案

我发现了这一点,在看到重试仅适用于异常后很明显,webClient 不会抛出异常,因为 clientResponse 对象只保存响应,只有当 bodyTo 被调用时才会在 http 状态上抛出异常,所以要解决这个问题,可以模仿这种行为

I figured this out, which was apparent after seeing retry only works on exceptions, webClient doesn't throw the exception, since the clientResponse object just holds the response, only when bodyTo is called is the exception thrown on http status, so to fix this, one can mimic this behaviour

@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 等集成,但同时


EDIT one of the features with repeat/retry is that, it doesn't change the original request, in my case I needed to retrieve a new OAuth token, but the above sent the same (expired) token. I did figure a way to do this using exchange filter, once OAuth password-flow is in spring-security-2.0 I should be able to have this integrated with AccessTokens etc, but in the mean time

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("Authorization", "Bearer " + tokenProvider.getNewToken().toString()).build();
                        return next.exchange(retryRequest);
                    } else {
                        return Mono.just(clientResponse);
                    }
                });
    }

这篇关于添加重试WebClient的所有请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆