如何在Micronaut中的HttpClientFilter内重试HTTP客户端请求?

huangapple 未分类评论46阅读模式
英文:

How can I retry HTTP client requests within a HttpClientFilter using Micronaut?

问题

我已经实现了一个Micronaut的HttpClientFilter来为所有发送到第三方服务的请求添加一个缓存的Bearer令牌,但是这个令牌相当频繁地过期。当发生这种情况时,我想重新验证下游API并在发生这种情况时重试请求,但似乎没有明显的方法来实现这一点。到目前为止,我只是简单地第二次调用proceed,但这会导致抛出一个“索引超出范围”的错误(我认为这里是应该抛出的异常,但这里似乎存在一个Micronaut的错误)。我所拥有的最小化的代码如下:

import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.filter.ClientFilterChain;
import io.micronaut.http.filter.HttpClientFilter;
import io.reactivex.Flowable;

import javax.inject.Inject;

interface AuthTokenProvider {
    // 缓存
    Flowable<String> fetchToken();
    void invalidateToken();
}

@Filter(serviceId = "third-party-api")
public class AuthTokenFilter implements HttpClientFilter {
    @Inject AuthTokenProvider tokenProvider;

    private Flowable<HttpResponse<?>> buildRequestWithToken(MutableHttpRequest<?> request, ClientFilterChain chain) {
        return tokenProvider.fetchToken()
                .map(token -> request.bearerAuth(token))
                .flatMap(chain::proceed);
    }

    @Override
    public Flowable<HttpResponse<?>> doFilter(MutableHttpRequest<?> request, ClientFilterChain chain) {
        return buildRequestWithToken(request, chain)
                .onErrorResumeNext(err -> {
                    System.out.println("API请求失败,使令牌无效并重试");

                    tokenProvider.invalidateToken();
                    return buildRequestWithToken(request, chain);
                });
    }
}

有人可以建议正确的方法吗?

英文:

I've implemented a micronaut HttpClientFilter to add a cached bearer token for all requests to a 3rd party service, however this token expires fairly regularly. I would like to reauthenticate with the downstream API and retry the request when this happens, but there doesn't seem to be an obvious way to do this. So far I'm simply calling proceed a second time, however this causes an Index out of bounds error to be thrown (I think that this is the exception that is supposed to be thrown, but there appears to be a bug in Micronaut here). Minimal reduction of what I've got is below:

import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.client.exceptions.HttpClientResponseException;
import io.micronaut.http.filter.ClientFilterChain;
import io.micronaut.http.filter.HttpClientFilter;
import io.reactivex.Flowable;

import javax.inject.Inject;

interface AuthTokenProvider {
    // cached
    Flowable&lt;String&gt; fetchToken();
    void invalidateToken();
}

@Filter(serviceId = &quot;third-party-api&quot;)
public class AuthTokenFilter implements HttpClientFilter {
    @Inject AuthTokenProvider tokenProvider;

    private Flowable&lt;HttpResponse&lt;?&gt;&gt; buildRequestWithToken(MutableHttpRequest&lt;?&gt; request, ClientFilterChain chain) {
        return tokenProvider.fetchToken()
                .map(token -&gt; request.bearerAuth(token))
                .flatMap(chain::proceed);
    }

    @Override
    public Flowable&lt;HttpResponse&lt;?&gt;&gt; doFilter(MutableHttpRequest&lt;?&gt; request, ClientFilterChain chain) {
        return buildRequestWithToken(request, chain)
                .onErrorResumeNext(err -&gt; {
                    System.out.println(&quot;API request failed, invalidating token and retrying&quot;);

                    tokenProvider.invalidateToken();
                    return buildRequestWithToken(request, chain);
                });
    }
}

Can anyone suggest the correct way to do this?

答案1

得分: 0

  1. 您可以在 application.yml 中使用 advanced-expiration 属性。如果将其设置为 200 秒,那么 Micronaut 将在实际到期前 200 秒将令牌视为已过期。https://micronaut-projects.github.io/micronaut-security/latest/guide/#io.micronaut.security.oauth2.configuration.OauthClientConfigurationProperties$ClientCredentialsConfigurationProperties
  2. 您可以在这个幻灯片第 18 页中使用 Micronaut 提供的 retry 注解。https://objectcomputing.com/files/6315/7297/3014/Slide_Deck_Micronaut_Declarative_HTTP_Client_Webinar.pdf
英文:
  1. You can use advanced-expiration property in application.yml If you set it to 200secs then micronaut considers the token expired 200sec before the actual expiry period. https://micronaut-projects.github.io/micronaut-security/latest/guide/#io.micronaut.security.oauth2.configuration.OauthClientConfigurationProperties$ClientCredentialsConfigurationProperties
  2. You can use retry annotation provided by micronaut in 18th page in this deck https://objectcomputing.com/files/6315/7297/3014/Slide_Deck_Micronaut_Declarative_HTTP_Client_Webinar.pdf

huangapple
  • 本文由 发表于 2020年4月6日 13:24:12
  • 转载请务必保留本文链接:https://java.coder-hub.com/61053425.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定