Skip to content

Instantly share code, notes, and snippets.

@jc-lab
Last active April 13, 2021 04:18
Show Gist options
  • Save jc-lab/e0c58a8a91ddd4023d273a3c05610eb1 to your computer and use it in GitHub Desktop.
Save jc-lab/e0c58a8a91ddd4023d273a3c05610eb1 to your computer and use it in GitHub Desktop.
spring-cloud-gateway환경에서 도메인에 따라 특정 서비스에 대해 테스트서버로 연결합니다
package your.package;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
@Component
public class TestableGatewayFilter implements GlobalFilter, Ordered {
@Autowired
private DiscoveryClient discoveryClient;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI requestUri = exchange.getRequest().getURI();
Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances(route.getUri().getHost());
System.out.println("requestUri " + requestUri.toString());
if(serviceInstanceList.size() > 0) {
for (ServiceInstance serviceInstance : serviceInstanceList) {
String testDomain = serviceInstance.getMetadata().get("test-domain");
if (testDomain != null) {
if (testDomain.equalsIgnoreCase(requestUri.getHost()) || true) {
try {
URI newUri = new URI(requestUri.getScheme(), requestUri.getUserInfo(), serviceInstance.getHost(), serviceInstance.getPort(), requestUri.getPath(), requestUri.getQuery(), requestUri.getFragment());
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newUri);
System.out.println("Redirect to test server : " + requestUri.toString() + " => " + exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR));
break;
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return LOWEST_PRECEDENCE;
}
}
@thghu123
Copy link

질문이 있습니다. Custom 필터로 적용 시에는 Ordered를 사용해도 적용이 안 됩니다. 내부적으로 라우팅을 결정하는 필터보다 이른 순서로 Path가 적용되야하는 것 같은데, 글로벌 필터에서만 적용되는 부분일까요?

@jc-lab
Copy link
Author

jc-lab commented Apr 13, 2021

@thghu123

질문이 있습니다. Custom 필터로 적용 시에는 Ordered를 사용해도 적용이 안 됩니다. 내부적으로 라우팅을 결정하는 필터보다 이른 순서로 Path가 적용되야하는 것 같은데, 글로벌 필터에서만 적용되는 부분일까요?

https://github.com/spring-cloud/spring-cloud-gateway/blob/6466f7342f1474408181678b63c3c2be0aa01b99/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilter.java#L69
를 보면 ReactiveLoadBalancerClientFilter 의 Order가 10150으로 나와있습니다. 이보다 낮은 숫자 (e.g. -1) 으로 바꾸면 될거같습니다.

@thghu123
Copy link

답변 정말 감사드립니다. 아무래도 ReactiveLoadBalancerClientFilter가 GlobalFilter 필터를 상속받고 있어 [글로벌필터] -> [개별필터] -> [개별필터 종료] -> [글로벌필터 종료] 순서로 진행되는 SCG에서 개별 필터가 Order를 통해 10150 이전의 순서를 가지기 어려워보입니다. 다른 방법이 있는지 찾아보겠지만 답변 감사드립니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment