[英]Spring Cloud Gateway - set Different Proxy for each route
Is their any way we can configure proxy for each route.他们是否可以通过任何方式为每条路由配置代理。
Incoming request A -> route A matched -> just forward to target system Incoming request B -> route B matched -> set proxy for target system call -> forward to target system using the proxy传入请求 A -> 路由 A 匹配 -> 仅转发到目标系统 传入请求 B -> 路由 B 匹配 -> 为目标系统调用设置代理 -> 使用代理转发到目标系统
if I use set proxy using spring cloud gateway it is getting applied to all the routes如果我使用 spring 云网关设置代理,它将被应用于所有路由
spring.cloud.gateway.httpclient.proxy.host= spring.cloud.gateway.httpclient.proxy.port= spring.cloud.gateway.httpclient.proxy.host= spring.cloud.gateway.httpclient.proxy.port=
Do you have any idea/ link/ code snippet how to solve that issue?你有任何想法/链接/代码片段如何解决这个问题吗? Any hint is welcome.欢迎任何提示。
spring:
cloud:
gateway:
routes:
- id: route1
metadata:
proxy-host: proxyhost
proxy-port: 1000
predicates:
- Path=...
uri: ...
- id: route2
metadata:
proxy-host: proxyhost2
proxy-port: 1000
predicates:
- Path=...
uri: ...
kotlin科特林
@Component
class CustomNettyRoutingFilter(
private val httpClient: HttpClient,
headersFiltersProvider: ObjectProvider<List<HttpHeadersFilter>>,
properties: HttpClientProperties,
) : NettyRoutingFilter(
httpClient,
headersFiltersProvider,
properties
) {
private val httpClientCacheMap: ConcurrentMap<String, HttpClient> = ConcurrentHashMap()
override fun getHttpClient(route: Route, exchange: ServerWebExchange): HttpClient {
val proxyHost = route.metadata["proxy-host"] as? String
val proxyPort = route.metadata["proxy-port"] as? Int
return httpClientCacheMap.getOrPut(route.id) {
when {
proxyHost != null && proxyPort != null -> {
httpClient.proxy { proxySpec ->
proxySpec.type(ProxyProvider.Proxy.HTTP)
.host(proxyHost)
.port(proxyPort)
}
}
else -> httpClient
}
}
}
}
Is this gonna help you?这会帮助你吗?
In my service, every client has their own API server.在我的服务中,每个客户端都有自己的 API 服务器。 So different endpoints are assigned according to the clientId
by the OriginMappingFilter
.因此OriginMappingFilter
会根据clientId
分配不同的端点。
For example, After authentication,例如,认证后,
if clientId header matched client1,如果 clientId 标头与 client1 匹配,
http://gateway.com/shops/every-resource is reached to http://client1.com/shops/every-resource http://gateway.com/shops/every-resource到达http://client1.com/shops/every-resource
if clientId header matched client2,如果 clientId 标头与 client2 匹配,
http://gateway.com/shops/every-resource is reached to http://client2.com/shops/every-resource http://gateway.com/shops/every-resource到达http://client2.com/shops/every-resource
@SpringBootApplication
public class GatewayApplication {
@Value("${token.secret}")
String tokenSecret;
@Autowired
private AuthenticationFilter authenticationfilter;
@Autowired
private OriginMappingFilter originMappingFilter;
public static void main(String[] args) {
SpringApplication.run(AutomangatewayApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/clients/*/tokens-with/*").uri("http://localhost:8081"))
.route(r -> r.path("/shops/**").filters(f -> f.filter(authenticationfilter).filter(originMappingFilter)).uri("no://op"))
.build();
}
@Bean
public TokenUtils tokenUtils() {
return new TokenUtils(tokenSecret);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Component
public class OriginMappingFilter implements GatewayFilter, Ordered {
private static final String LEGACY_WEBSERVER_ORIGIN = "http://localhost:9095";
@Autowired
private RestTemplate restTemplate;
@Override
public int getOrder() {
return 10000;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
try {
ServerHttpRequest request = exchange.getRequest();
String clientId = request.getHeaders().get("clientId").get(0);
String origin = originOfClient(clientId);
URI newURI = new URI(origin + request.getPath().pathWithinApplication().value());
System.out.println("destination: " + newURI.toString());
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, newURI);
return chain.filter(exchange);
} catch (URISyntaxException e ) {
e.printStackTrace();
throw new IllegalStateException("can't map client to origin",e);
} catch (HttpServerErrorException e) {
e.printStackTrace();
throw new IllegalStateException("can't access to client resource",e);
}
}
private String originOfClient(String clientId) {
ResponseEntity<String> response = restTemplate.getForEntity(LEGACY_WEBSERVER_ORIGIN+"/clients/"+clientId+"/ip", String.class);
String ip = response.getBody();
String origin = "http://"+ip+":8082";
return origin;
}
}
I could solve it like this我可以这样解决
Step 1 : Define metadata for proxy in route第 1 步:为路由中的代理定义元数据
@Configuration
public class MyRouteConfiguration {
@Bean
public RouteLocator routes( //
final RouteLocatorBuilder locatorBuilder, //
final MyRoutingConfiguration routingConfiguration) {
RouteLocatorBuilder.Builder builder = locatorBuilder.routes();
routingConfiguration //
.getRoutings() //
.stream() //
.forEach(routing -> builder //
.route(p -> p //
.path(toPatternString(routing.getPaths())) //
.filters(f -> f //
.rewritePath(routing.getRewriteRegex(), routing.getRewriteReplacement()) //
.metadata("proxy-host", routing.getProxyHost()) //
.metadata("proxy-port", routing.getProxyPort()) //
.metadata("proxy-username", routing.getProxyUsername()) //
.metadata("proxy-password", routing.getProxyPassword()) //
.uri(routing.getUri())));
return builder.build();
}
Step 2 : Create a component extending from NettyRoutingFilter
第 2 步:创建一个从NettyRoutingFilter
扩展的组件
@Component
public class HttpClientFilter extends NettyRoutingFilter {
public HttpClientFilter(HttpClient httpClient, ObjectProvider<List<HttpHeadersFilter>> headersFiltersProvider,
HttpClientProperties properties) {
super(httpClient, headersFiltersProvider, properties);
}
@Override
protected HttpClient getHttpClient(Route route, ServerWebExchange exchange) {
Map<String, Object> metadata = route.getMetadata();
String proxyHost = (String) metadata.getOrDefault("proxy-host", "default-host");
String proxyPort = (String) metadata.getOrDefault("proxy-port", "default-port");
String username = (String) metadata.getOrDefault("proxy-username", "default-user");
String pass = (String) metadata.getOrDefault("proxy-password", "default-password");
return super.getHttpClient(route, exchange) .proxy(proxy -> proxy //
.type(ProxyProvider.Proxy.HTTP) //
.host(proxyHost) //
.port(Integer.valueOf(proxyPort)) //
.username(username) //
.password(password -> password = pass));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.