[RequestProxyFilter, order 4]
→
package com.ktds.act.apigw.filter;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
import java.net.URI;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.RouteMetadataUtils;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import com.ktds.act.apigw.api.db.entity.AdmApiDply;
import com.ktds.act.apigw.filter.function.SetExchangeRequest;
import com.ktds.act.apigw.filter.model.AgwErrorDto;
import com.ktds.act.apigw.filter.model.TransactionDto;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class RequestProxyFilter implements GlobalFilter, Ordered {
@Autowired
private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyFilter;
@Autowired
private SetExchangeRequest setExchangeRequest;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
TransactionDto transaction = (TransactionDto) exchange.getAttribute(TransactionDto.TRANSACTION);
//Thread.currentThread().setName(transaction.getComn().getTxId());
log.info("RequestProxyFilter - Start");
try {
**//응용계층의 네트워크 프로토콜이 NONE이 아닐때만 작업을 시작한다. (어떤 프로토콜인지)
//NONE이면 아무것도 하지 않고 넘어간다.**
if(!"NONE".equals(transaction.getReq().getEdpt().getProt())){
**//여러개 Edpt중에 원하는 걸로 chooseUrl한다????**
Optional<String> endpoint = transaction.getReq().getEdpt().chooseUrl();
// String endpoint = endpointService.getEndpoint(transaction.getReq().getEdpt());
// uriOut을 통해 endpoint 도출 **(어디로 연동할지에 대한 정보를 세팅한다)**
AdmApiDply api = transaction.getComn().getApi();
String uriOut = setUriOut(transaction);
String uriFullPath = endpoint.get() + uriOut;
log.info("Route Endpoint : " + uriFullPath);
**//routing 정보 재정의**
// 연동포인트(Route) 정보 **(연동할때 timeout과 같은 옵션 세팅)**
String routeId = "custom-route";
Integer connectionTimeout = (int) api.getTimeOut();
Number readTimeout = api.getTimeOut();
// 연동포인트(Route) 변경 **(Yaml에서 그냥 뚫려 있던 Routing path들 재 세팅)**
Route originalRoute = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
Route newRoute = Route.async()
.asyncPredicate(originalRoute.getPredicate())
.id(routeId)
.uri(uriFullPath)
.metadata(RouteMetadataUtils.CONNECT_TIMEOUT_ATTR, connectionTimeout)
.metadata(RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR, readTimeout)
.build();
**//exchange에 새로 갱신된 route정보를 덮어씌워준다. (이 부분이 완벽히 이해는 안감)**
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, newRoute);
log.debug("exchange header before : {}",exchange.getRequest().getHeaders());
**//변환된 정보를 재 정의 (request) -> 이전에 핸들러로 바뀔수 있으니까**
URI newUri = exchange.getRequest().getURI(); **//requestURI**
MultiValueMap<String, String> queryParam = transaction.getReq().getQueryParams();
if((queryParam != null && !queryParam.isEmpty())
|| !uriOut.equals(newUri.getPath())
|| !exchange.getRequest().getMethod().matches(transaction.getReq().getMeth())) {
if(queryParam != null && !queryParam.isEmpty()) {
newUri = setNewUriWithQueryParams(exchange, transaction);
}
HttpMethod meth = HttpMethod.valueOf(transaction.getReq().getMeth());
ServerHttpRequest serverHttpRequest =exchange.getRequest().mutate()
.uri(newUri)
.path(uriOut)
.method(meth)
.build();
exchange = exchange.mutate().request( serverHttpRequest ).build();
log.debug("exchange header after : {}",exchange.getRequest().getHeaders());
}
}
} catch (NullPointerException e) {
log.error("Invalid endpoint url", e);
transaction.setError(AgwErrorDto.INTERNAL_SERVER_ERROR);
return Mono.error(e);
}catch (Exception e) {
log.error("Invalid endpoint url", e);
transaction.setError(AgwErrorDto.INTERNAL_SERVER_ERROR);
return Mono.error(e);
}
log.info("RequestProxyFilter - End");
//Transaction객체에 있는 request body 정보대로 exchange 객체의 request body 설정
if(transaction.getReq().isBodyChg()){
return modifyRequestBodyFilter
.apply(
new ModifyRequestBodyGatewayFilterFactory.Config()
.setRewriteFunction(byte[].class, byte[].class, setExchangeRequest))
.filter(exchange, chain);
}
transaction.setReqComplete();
return chain.filter(exchange);
}
private URI setNewUriWithQueryParams(ServerWebExchange exchange, TransactionDto transaction) {
URI uri = exchange.getRequest().getURI();
StringBuilder query = new StringBuilder();
MultiValueMap<String, String> txQueryParams = transaction.getReq().getQueryParams();
for(String key : txQueryParams.keySet()){
query.append(key);
query.append('=');
query.append(txQueryParams.get(key).get(0));
query.append('&');
}
return UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(true).toUri();
}
private String setUriOut(TransactionDto transaction) {
if(!StringUtils.hasText(transaction.getReq().getOut())){
return transaction.getReq().getIn();
} else {
return transaction.getReq().getOut();
}
}
@Override
public int getOrder() {
return 4;
}
}