Spring网关-多个httpclient在Spring网关?



我有许多过滤器用来处理不同的请求。

我重写了Spring Gateway提供的默认netty httpClient,所以我可以在我的情况下以编程方式设置一些sslContext - mTLS。这很好,但我还需要有第二个netty httpClient,这样我就可以连接到其他服务器,根本没有ssl,或者只是常规的tls。

我想知道是否有可能在特定的过滤器上设置sslContext,或者根据过滤器或spring网关提供的其他扩展点决定使用什么httpClient。

你认为有可能有多个httpclient并决定使用哪一个?

我尝试创建一个新的bean,它配置一个httpClient,并设置一些sslContext像这样:

@Bean
public reactor.netty.http.client.HttpClient httpClient() {
final PrivateKey privateKey = getPrivateKey();
final X509Certificate x509Certificate = getX509Certificate();
final SslContext sslContext =
SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.keyManager(privateKey, x509Certificate)
.build();
return reactor.netty.http.client.HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
}

当我使用这个httpClient通过mTLS连接时,它工作得很好,但我想根据特定的过滤器决定使用什么httpClient。

我有一个类似的需求,我需要为不同的路由使用不同的httpclient。我的方法是创建一个类来扩展org.springframework.cloud.gateway.filter.NettyRoutingFilter类并覆盖HttpClient getHttpClient(Route route, ServerWebExchange exchange)方法。在该方法中,您可以指定应该将哪个HttpClient用于哪个路由。下面是示例类。

import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.config.HttpClientProperties;
import org.springframework.cloud.gateway.filter.NettyRoutingFilter;
import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.netty.http.client.HttpClient;
@Component
public class CustomNettyRoutingFilter extends NettyRoutingFilter {
private final HttpClient customClientOne;
private final HttpClient customClientTwo;


public CustomNettyRoutingFilter(HttpClient httpClient,
ObjectProvider<List<HttpHeadersFilter>> headersFiltersProvider, HttpClientProperties properties) {
super(httpClient, headersFiltersProvider, properties);
customClientOne=createCustomClientOne();
customClientTwo=createCustomClientTwo();
}
@Override
protected HttpClient getHttpClient(Route route, ServerWebExchange exchange) {
if(shouldUseClientOne(route)) {
return customClientOne;
}
if(shouldUseClientTwo(route)) {
return customClientTwo;
}
//If handeling another route use the default client.
return super.getHttpClient(route, exchange);
}

@Override
public int getOrder() {
return return super.getOrder() - 1;
}   

//Other methods here
}

如果CustomNettyRoutingFilter类的实例在ApplicationContext中作为bean加载,它将被添加到每个请求使用的GlobalFilters列表中。(在这种情况下,我使用@Component)。由Spring Cloud Gateway创建的原始NettyRoutingFilter仍然在全局过滤器列表中,为了确保自定义过滤器在原始过滤器之前触发,我覆盖了getOrder()方法,并使它返回的值比NettyRoutingFilter返回的值少一个(低顺序值对应高优先级)。我不知道是否需要重写getOrder()方法,因为它对我有用,但我认为重写是更安全的选择。(你可以在这里看到使用执行器端点的全局过滤器列表,见:这里)

我不确定这是否是做类似事情的最佳实践方式,但对我来说确实有效。