使用 Spring Cloud Gateway 过滤器重试带有修改后的标头的 REST 调用?

问题描述 投票:0回答:1

我目前正在开发一个用于开发的 REST“代理”。这个想法是在命令行上启动一个 jar,为其提供“代理”REST API 的基本 URL 和用于身份验证的现有密钥。代理处理身份验证/续订并将所有 REST 调用转发到目标 API。

我认为 Spring Cloud Gateway 可能非常适合此目的,并且使用请求链已经成功地使身份验证方面的工作正常进行:

@Configuration
public class FilterConfiguration {

    @Bean
    public RouteLocator mock(RouteLocatorBuilder builder, @Value("${gateway.url}") String url, @Value("${secret.key}") String secretKey, MyGatewayFilterFactory filterFactory) {
        return builder.routes()
            .route("pass-through", predicateSpec -> predicateSpec
                .path("/authentication/sign/in/**", "/authentication/renew/**")
                .uri(url))
            .route("requires-auth", predicateSpec -> predicateSpec
                .alwaysTrue()
                .filters(gatewayFilterSpec -> gatewayFilterSpec
                    .filter(filterFactory.apply(new MyGatewayFilterFactory.Config(secretKey)))
                )
                .uri(url))
            .build();
    }
}
@Component
@RequiredArgsConstructor
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory .Config> {

    private final WebClient webClient;

    @Override
    public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
        return (exchange, chain) -> Optional.of(AccessTokensHolder.tokens)
            .map(AtomicReference::get)
            .map(Mono::just)
            .orElseGet(() -> this.signIn(config.getSecretKey()))
            .flatMap(accessTokens -> {
                exchange.getRequest()
                    .mutate()
                    .header(HttpHeaders.AUTHORIZATION, String.format("%s %s", accessTokens.getType(), accessTokens.getAccessToken()));
                return chain.filter(exchange);
            })
            .onErrorResume(t -> Mono.empty())
            .then(Mono.fromRunnable(this.postRequest(exchange)));
    }

    private Mono<AccessTokens> signIn(String secretKey) {
        // uses the webClient to get the access tokens for the secretKey ...
    }

    private Runnable postRequest(ServerWebExchange exchange) {
        return () -> {
            ServerHttpResponse response = exchange.getResponse();
            if (HttpStatus.PRECONDITION_FAILED.equals(response.getStatusCode())) {
                
                // todo : HELP!
            }
        };
    }

    @Data
    @RequiredArgsConstructor
    public static class Config {

        public final String secretKey;
    }

    private static final class AccessTokensHolder {
        private static final AtomicReference<AccessTokens> tokens = new AtomicReference<>();
    }
}

我的问题是响应的处理。如果经过身份验证的调用以 412 响应,我需要能够进行 webClient 调用来刷新访问令牌,然后再次执行原始调用(使用修改后的授权标头)。我不知道如何实现这一点(对于 SCG 和 WebFlux 来说相当新)...

(顺便说一句,如果有人知道更好/更简单的方法来实现这一点,我洗耳恭听!)

任何帮助将不胜感激!

干杯!

java spring-cloud spring-webflux spring-cloud-gateway spring-webclient
1个回答
0
投票

你能解决这个问题吗?我也遇到同样的问题但是不知道怎么解决!

© www.soinside.com 2019 - 2024. All rights reserved.