sk_fems_apigw commit
This commit is contained in:
@ -0,0 +1,32 @@
|
||||
package com.lsitc.fems.SpringCloudGateway;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
|
||||
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
|
||||
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class PassCorsRoutePredicateHandlerMapping extends RoutePredicateHandlerMapping {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PassCorsRoutePredicateHandlerMapping.class);
|
||||
|
||||
public PassCorsRoutePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator,
|
||||
GlobalCorsProperties globalCorsProperties, Environment environment) {
|
||||
super(webHandler, routeLocator, globalCorsProperties, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> getHandler(ServerWebExchange exchange) {
|
||||
logger.info("[PassCorsRoutePredicateHandlerMapping] getHandler");
|
||||
return getHandlerInternal(exchange).map(handler -> {
|
||||
logger.info(exchange.getLogPrefix() + "Mapped to " + handler);
|
||||
// CORS 체크 로직 제거
|
||||
return handler;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.lsitc.fems.SpringCloudGateway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
|
||||
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
|
||||
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringCloudGatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringCloudGatewayApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public RoutePredicateHandlerMapping passCorsRoutePredicateHandlerMapping(
|
||||
FilteringWebHandler webHandler, RouteLocator routeLocator,
|
||||
GlobalCorsProperties globalCorsProperties, Environment environment) {
|
||||
return new PassCorsRoutePredicateHandlerMapping(webHandler, routeLocator,
|
||||
globalCorsProperties, environment);
|
||||
}
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
|
||||
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
|
||||
* LS의 지적재산권 침해에 해당됩니다.
|
||||
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
|
||||
*
|
||||
* You are strictly prohibited to copy, disclose, distribute, modify, or use
|
||||
* this program in part or as a whole without the prior written consent of
|
||||
* LS. LS owns the intellectual property rights in
|
||||
* and to this program.
|
||||
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
|
||||
* Created : 2021.04.06
|
||||
*/
|
||||
package com.lsitc.fems.SpringCloudGateway.filter;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Component
|
||||
public class AuthFilter extends AbstractGatewayFilterFactory<Map> {
|
||||
private Logger logger = LoggerFactory.getLogger(AuthFilter.class);
|
||||
private String authServiceUrl = "";
|
||||
private String loginUrl = "";
|
||||
private String cookieId = "";
|
||||
private final WebClient webClient = WebClient.create();
|
||||
|
||||
public AuthFilter() {
|
||||
super(Map.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Map config) {
|
||||
authServiceUrl = config.get("authAPI").toString();
|
||||
cookieId = config.get("cookieId").toString();
|
||||
loginUrl = config.get("loginUrl").toString();
|
||||
|
||||
return (exchange, chain) -> {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
// 로그인 및 권한 Check 호출
|
||||
Mono<ClientResponse> authServiceResponse = callAuthService(request);
|
||||
// 후처리
|
||||
Mono<Void> middleService = authServiceResponse.flatMap(r -> processAuthResponse(exchange, chain, request, r));
|
||||
return middleService.then();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @methodName : resolveBodyFromRequest
|
||||
* @date : 2021.05.06
|
||||
* @desc : requestBody를 String으로 변환하여 반환한다.
|
||||
* @param serverHttpRequest
|
||||
* @return
|
||||
*/
|
||||
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
|
||||
// Get the request body
|
||||
Flux<DataBuffer> body = serverHttpRequest.getBody();
|
||||
AtomicReference<String> bodyRef = new AtomicReference<>();
|
||||
body.subscribe(buffer -> {
|
||||
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
|
||||
DataBufferUtils.release(buffer);
|
||||
bodyRef.set(charBuffer.toString());
|
||||
});
|
||||
// Get request body
|
||||
return bodyRef.get();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @methodName : callAuthService
|
||||
* @date : 2021.04.15
|
||||
* @desc : 로그인 및 권한 check API 호출
|
||||
* @param inputRequest
|
||||
* @return
|
||||
*/
|
||||
private Mono<ClientResponse> callAuthService(ServerHttpRequest inputRequest) {
|
||||
logger.info("requestURI : {}", inputRequest.getPath());
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("requestURI", inputRequest.getPath().toString());
|
||||
|
||||
if( inputRequest.getMethod().matches("POST") ) {
|
||||
//POST는 header에서
|
||||
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
|
||||
|
||||
logger.info("X-Fems-MenuId : {}", menuId);
|
||||
params.put("menuId", menuId.get(0));
|
||||
// String requestBodyStr = resolveBodyFromRequest(inputRequest);
|
||||
// ObjectMapper mapper = new ObjectMapper();
|
||||
// JsonNode actualObj;
|
||||
// try {
|
||||
// //requestBody
|
||||
// actualObj = mapper.readTree(requestBodyStr);
|
||||
// //menuId
|
||||
// params.put("menuId", actualObj.get("params").get("menuId") != null ? actualObj.get("params").get("menuId").asText() : "2");
|
||||
// } catch (Exception e) {
|
||||
// }
|
||||
} else {
|
||||
//POST는 queryString에서(e.g. menu)
|
||||
params.put("menuId", inputRequest.getQueryParams().getFirst("$menuId"));
|
||||
}
|
||||
System.out.println("getHeaders" + inputRequest.getHeaders());
|
||||
|
||||
System.out.println("authServiceUrl : " + authServiceUrl);
|
||||
System.out.println("cookieId : " + cookieId);
|
||||
System.out.println("getCookies : " + inputRequest.getCookies().toString());
|
||||
System.out.println("getFirst(cookieId) : " + inputRequest.getCookies().getFirst(cookieId));
|
||||
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(authServiceUrl)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
|
||||
.cookie(cookieId,
|
||||
inputRequest.getCookies().getFirst(cookieId) != null
|
||||
? inputRequest.getCookies().getFirst(cookieId).getValue()
|
||||
: "");
|
||||
request.bodyValue(params);
|
||||
return request.exchange();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @methodName : processMiddleResponse
|
||||
* @date : 2021.04.15
|
||||
* @desc :
|
||||
* @param exchange
|
||||
* @param chain
|
||||
* @param request
|
||||
* @param middleServiceResponse
|
||||
* @return
|
||||
*/
|
||||
private Mono<Void> processAuthResponse(ServerWebExchange exchange, GatewayFilterChain chain,
|
||||
ServerHttpRequest request, ClientResponse authServiceResponse) {
|
||||
if (authServiceResponse.statusCode().is2xxSuccessful()) {
|
||||
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
|
||||
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
|
||||
httpHeaders.set("Cookie",
|
||||
authServiceResponse.cookies().get(cookieId) != null
|
||||
? authServiceResponse.cookies().get(cookieId).get(0).toString()
|
||||
: "");
|
||||
}).build();
|
||||
|
||||
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
|
||||
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
|
||||
exchange.getResponse().addCookie(cookie);
|
||||
System.out.println("exchange.getResponse is2xxSuccessful" + exchange.getResponse());
|
||||
|
||||
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
|
||||
//// logger.info("retnCd :: {}", m.get("retnCd"));
|
||||
// });
|
||||
return chain.filter(modifiedExchange);
|
||||
} else {
|
||||
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getHeaders());
|
||||
System.out.println("exchange.getResponse else is2xxSuccessful" + exchange.getResponse().getCookies());
|
||||
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.OK);
|
||||
|
||||
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
|
||||
DataBuffer dataBuffer = null;
|
||||
|
||||
try {
|
||||
dataBuffer = bufferFactory
|
||||
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
|
||||
} catch (JsonProcessingException e) {
|
||||
dataBuffer = bufferFactory.wrap("".getBytes());
|
||||
}
|
||||
|
||||
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
|
||||
} else {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
|
||||
try {
|
||||
response.getHeaders().setLocation(new URI(loginUrl));
|
||||
} catch (URISyntaxException e) {
|
||||
// TODO Auto-generated catch block
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class HttpError {
|
||||
private String rtnCd;
|
||||
private String message;
|
||||
|
||||
HttpError(String rtnCd, String message) {
|
||||
this.rtnCd = rtnCd;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getRtnCd() {
|
||||
return rtnCd;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 상기 프로그램에 대한 저작권을 포함한 지적재산권은 LS ITC에 있으며,
|
||||
* LS와 명시적으로 허용하지 않은 사용, 복사, 변경, 제3자에의 공개, 배포는 엄격히 금지되며,
|
||||
* LS의 지적재산권 침해에 해당됩니다.
|
||||
* (Copyright ⓒ 2021 LS ITC. All Rights Reserved| Confidential)
|
||||
*
|
||||
* You are strictly prohibited to copy, disclose, distribute, modify, or use
|
||||
* this program in part or as a whole without the prior written consent of
|
||||
* LS. LS owns the intellectual property rights in
|
||||
* and to this program.
|
||||
* (Copyright ⓒ 2021 LS. All Rights Reserved| Confidential)
|
||||
* Created : 2021.05.06
|
||||
*/
|
||||
package com.lsitc.fems.SpringCloudGateway.filter;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered {
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
|
||||
if (exchange.getRequest().getHeaders().getContentType() == null || exchange.getRequest().getMethod().matches("GET")) {
|
||||
return chain.filter(exchange);
|
||||
} else {
|
||||
return DataBufferUtils.join(exchange.getRequest().getBody())
|
||||
.flatMap(dataBuffer -> {
|
||||
DataBufferUtils.retain(dataBuffer);
|
||||
Flux<DataBuffer> cachedFlux = Flux
|
||||
.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
|
||||
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
|
||||
exchange.getRequest()) {
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return cachedFlux;
|
||||
}
|
||||
};
|
||||
return chain.filter(exchange.mutate().request(mutatedRequest).build());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package com.lsitc.fems.SpringCloudGateway.filter;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Component
|
||||
public class MenuLogFilter extends AbstractGatewayFilterFactory<Map> {
|
||||
private Logger logger = LoggerFactory.getLogger(MenuLogFilter.class);
|
||||
private String menuLogServiceUrl = "";
|
||||
private String loginUrl = "";
|
||||
private String cookieId = "";
|
||||
private final WebClient webClient = WebClient.create();
|
||||
|
||||
|
||||
public MenuLogFilter() {
|
||||
super(Map.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Map config) {
|
||||
menuLogServiceUrl = config.get("menuLogAPI").toString();
|
||||
cookieId = config.get("cookieId").toString();
|
||||
loginUrl = config.get("loginUrl").toString();
|
||||
|
||||
return (exchange, chain) -> {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
// 로그인 및 권한 Check 호출
|
||||
Mono<ClientResponse> menuLogServiceResponse = callMenuLogService(request);
|
||||
// 후처리
|
||||
Mono<Void> middleService = menuLogServiceResponse.flatMap(r -> processMenuLogResponse(exchange, chain, request, r));
|
||||
return middleService.then();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Mono<ClientResponse> callMenuLogService(ServerHttpRequest inputRequest) {
|
||||
logger.info("callMenuLogService : {}", inputRequest.getPath());
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("requestURI", inputRequest.getPath().toString());
|
||||
|
||||
if( inputRequest.getMethod().matches("POST") ) {
|
||||
//POST는 header에서
|
||||
List<String> menuId = inputRequest.getHeaders().get("X-Fems-MenuId");
|
||||
|
||||
logger.info("X-Fems-MenuId : {}", menuId);
|
||||
params.put("menuId", menuId.get(0));
|
||||
} else {
|
||||
//POST는 queryString에서(e.g. menu)
|
||||
String menuId = inputRequest.getQueryParams().getFirst("$menuId");
|
||||
params.put("menuId", menuId == null?"0":menuId);
|
||||
}
|
||||
|
||||
WebClient.RequestBodySpec request = webClient.method(HttpMethod.POST).uri(menuLogServiceUrl)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
|
||||
.cookie(cookieId,
|
||||
inputRequest.getCookies().getFirst(cookieId) != null
|
||||
? inputRequest.getCookies().getFirst(cookieId).getValue()
|
||||
: "");
|
||||
request.bodyValue(params);
|
||||
return request.exchange();
|
||||
}
|
||||
private Mono<Void> processMenuLogResponse(ServerWebExchange exchange, GatewayFilterChain chain,
|
||||
ServerHttpRequest request, ClientResponse authServiceResponse) {
|
||||
if (authServiceResponse.statusCode().is2xxSuccessful()) {
|
||||
// 로그인 및 권한 체크 결과 정상이면 새로 발급된 쿠키를 담아준다.
|
||||
ServerHttpRequest modifiedRequest = request.mutate().headers((httpHeaders) -> {
|
||||
httpHeaders.set("Cookie",
|
||||
authServiceResponse.cookies().get(cookieId) != null
|
||||
? authServiceResponse.cookies().get(cookieId).get(0).toString()
|
||||
: "");
|
||||
}).build();
|
||||
|
||||
ServerWebExchange modifiedExchange = exchange.mutate().request(modifiedRequest).build();
|
||||
ResponseCookie cookie = authServiceResponse.cookies().get(cookieId).get(0);
|
||||
exchange.getResponse().addCookie(cookie);
|
||||
|
||||
// authServiceResponse.bodyToMono(Map.class).subscribe(m -> {
|
||||
//// logger.info("retnCd :: {}", m.get("retnCd"));
|
||||
// });
|
||||
return chain.filter(modifiedExchange);
|
||||
} else {
|
||||
if (exchange.getRequest().getHeaders().getAccept().contains(MediaType.APPLICATION_JSON)) {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.OK);
|
||||
|
||||
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
|
||||
DataBuffer dataBuffer = null;
|
||||
|
||||
try {
|
||||
dataBuffer = bufferFactory
|
||||
.wrap(objectMapper.writeValueAsBytes(new HttpError("-1", "문제가 발생하였습니다. 관리자에게 문의하세요.")));
|
||||
} catch (JsonProcessingException e) {
|
||||
dataBuffer = bufferFactory.wrap("".getBytes());
|
||||
}
|
||||
|
||||
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
|
||||
} else {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.MOVED_TEMPORARILY);
|
||||
try {
|
||||
response.getHeaders().setLocation(new URI(loginUrl));
|
||||
} catch (URISyntaxException e) {
|
||||
// TODO Auto-generated catch block
|
||||
}
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class HttpError {
|
||||
private String rtnCd;
|
||||
private String message;
|
||||
|
||||
HttpError(String rtnCd, String message) {
|
||||
this.rtnCd = rtnCd;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getRtnCd() {
|
||||
return rtnCd;
|
||||
}
|
||||
}
|
||||
}
|
241
src/main/resources/application.yaml
Normal file
241
src/main/resources/application.yaml
Normal file
@ -0,0 +1,241 @@
|
||||
# 공통
|
||||
spring:
|
||||
application:
|
||||
#업무명
|
||||
name: apiGw
|
||||
serverip: localhost
|
||||
profiles:
|
||||
#프로파일(local:로컬환경, dev:개발환경(추가환경개발), docker:운영 택1)
|
||||
active: local
|
||||
#로깅관련
|
||||
logging:
|
||||
loginLogEnable: true
|
||||
menuCnctLogEnable: true
|
||||
level:
|
||||
root: DEBUG
|
||||
#logging
|
||||
config: classpath:logback_spring.xml
|
||||
file:
|
||||
path: logs
|
||||
max-history: 30
|
||||
max-size: 100MB
|
||||
---
|
||||
##############
|
||||
####local#####
|
||||
##############
|
||||
#AuthFilter정의
|
||||
AuthFilter: &AuthFilter
|
||||
- name: AuthFilter
|
||||
args:
|
||||
authAPI: http://localhost:8080/isValidToken
|
||||
cookieId: FEMS_SESSION
|
||||
loginUrl: /login
|
||||
MenuLogFilter: &MenuLogFilter
|
||||
- name: MenuLogFilter
|
||||
args:
|
||||
menuLogAPI: http://localhost:8080/menuLogCont
|
||||
cookieId: FEMS_SESSION
|
||||
loginUrl: /login
|
||||
#MenuLogFilter: &MenuLogFilter
|
||||
# - name: MenuLogFilter
|
||||
# args:
|
||||
# menuLogAPI: http://localhost:9999/menuLogCont
|
||||
# cookieId: FEMS_SESSION
|
||||
# loginUrl: http://localhost:9999/login
|
||||
spring:
|
||||
profiles: local
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
cloud:
|
||||
gateway:
|
||||
globalcors:
|
||||
corsConfigurations:
|
||||
'[/**]':
|
||||
allowedOrigins: "*"
|
||||
#timeout관련 설정
|
||||
httpclient:
|
||||
connect-timeout: 300000 # 30초
|
||||
response-timeout: 300s # 30초, 글로벌 설정시 seconds
|
||||
pool:
|
||||
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
|
||||
#routing관련 설정
|
||||
routes:
|
||||
# withoutAuth
|
||||
- id: withOutAuth #id
|
||||
uri: http://localhost:8080/comm #forward url
|
||||
predicates:
|
||||
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /sso, /comm/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
|
||||
# withOutEms
|
||||
- id: withOutEms
|
||||
uri: http://localhost:8082/
|
||||
predicates:
|
||||
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
|
||||
# vuePage
|
||||
- id: vuePage
|
||||
uri: http://localhost:3000/
|
||||
filters:
|
||||
- <<: *MenuLogFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/ems/**/*Page, /comm/**/*Page
|
||||
# vue.js
|
||||
- id: vue #id
|
||||
uri: http://localhost:3000/ #forward url
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /ems/*Page, /comm/*Page, /iframe/**, /
|
||||
# vue sample
|
||||
- id: vueSample #id
|
||||
uri: http://localhost:3010/ #forward url
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/_nuxt/sample/**, /sample/*Page
|
||||
# comm
|
||||
- id: comm #id
|
||||
uri: http://localhost:8080 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/comm/** #, /
|
||||
# ems
|
||||
- id: ems #id
|
||||
uri: http://localhost:8082 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/ems/base/**, /ems/api/** ,/ems/bala/**, /ems/effc/**
|
||||
# ems_fopm
|
||||
- id: ems_fopm #id
|
||||
uri: http://localhost:8084 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/fopm/**
|
||||
# drp
|
||||
- id: drp #id
|
||||
uri: http://localhost:8086 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/ems/drp/**
|
||||
# cmms
|
||||
- id: cmms #id
|
||||
uri: http://localhost:8089 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/cmms/**
|
||||
# sample
|
||||
- id: sample #id
|
||||
uri: http://localhost:8090 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/sample/**
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "gateway"
|
||||
endpoint:
|
||||
gateway:
|
||||
enabled: true
|
||||
server:
|
||||
port: 9999
|
||||
|
||||
---
|
||||
###############################
|
||||
#### Cloud(Kube) #####
|
||||
###############################
|
||||
AuthFilter: &AuthFilter
|
||||
- name: AuthFilter
|
||||
args:
|
||||
authAPI: http://skfems-comm:8080/isValidToken
|
||||
cookieId: FEMS_SESSION
|
||||
loginUrl: /login
|
||||
MenuLogFilter: &MenuLogFilter
|
||||
- name: MenuLogFilter
|
||||
args:
|
||||
menuLogAPI: http://skfems-comm:8080/menuLogCont
|
||||
cookieId: FEMS_SESSION
|
||||
loginUrl: /login
|
||||
spring:
|
||||
profiles: cloud_kube
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
cloud:
|
||||
gateway:
|
||||
globalcors:
|
||||
corsConfigurations:
|
||||
'[/**]':
|
||||
allowedOrigins: "*"
|
||||
#timeout관련 설정
|
||||
httpclient:
|
||||
connect-timeout: 300000 # 30초
|
||||
response-timeout: 300s # 30초, 글로벌 설정시 seconds
|
||||
pool:
|
||||
max-idle-time: 300000 # 5분간 휴상태이면 회수 처리
|
||||
#routing관련 설정
|
||||
routes:
|
||||
# withoutAuth
|
||||
- id: withOutAuth #id
|
||||
uri: http://skfems-comm:8080/ #forward url
|
||||
predicates:
|
||||
- Path= /loginChk, /logout, /isValidToken, /menuLogCont, /comm/base/SystemLogReadCtr/saveMenuCnctLog, /loginProc #, /login
|
||||
# withOutEms
|
||||
- id: withOutEms
|
||||
uri: http://skfems-ems:8082/
|
||||
predicates:
|
||||
- Path=/ems/effc/MdlDataSetCtr/selectMdlOpen
|
||||
# vueCommAuthPage
|
||||
- id: vueCommAuthPage
|
||||
uri: http://skfems-ui:3000/
|
||||
filters:
|
||||
- <<: *MenuLogFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/comm/**/*Page, /ems/**/*Page
|
||||
# vue.js
|
||||
- id: vue #id
|
||||
uri: http://skfems-ui:3000/ #forward url
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/_nuxt/comm/**, /__webpack_hmr/**, /_loading/**, /favicon.ico, /login, /iframe/**, /
|
||||
# comm
|
||||
- id: comm #id
|
||||
uri: http://skfems-comm:8080 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/comm/**
|
||||
# ems
|
||||
- id: ems #id
|
||||
uri: http://skfems-ems:8082 #forward url
|
||||
filters:
|
||||
- <<: *AuthFilter
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/ems/**
|
||||
# webHmi
|
||||
- id: webHmi #id
|
||||
uri: http://skfems-fuxa:1881 #forward url
|
||||
predicates:
|
||||
#라우팅할 path
|
||||
- Path=/webHmi/**
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "gateway"
|
||||
endpoint:
|
||||
gateway:
|
||||
enabled: true
|
||||
server:
|
||||
port: 9999
|
66
src/main/resources/logback_spring.xml
Normal file
66
src/main/resources/logback_spring.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 60초마다 설정 파일의 변경을 확인 하여 변경시 갱신 -->
|
||||
<configuration scan="true" scanPeriod="60 seconds">
|
||||
<!--springProfile 태그를 사용하면 logback 설정파일에서 복수개의 프로파일을 설정할 수 있다. -->
|
||||
<springProperty scope="context" name="LOG_LEVEL" source="logging.level.root" />
|
||||
<!-- log file path -->
|
||||
<springProperty scope="context" name="LOG_PATH" source="logging.file.path"/>
|
||||
<!-- log file name -->
|
||||
<springProperty scope="context" name="LOG_FILE_NAME" source="spring.application.name"/>
|
||||
<!-- log file size -->
|
||||
<springProperty scope="context" name="LOG_MAX-SIZE" source="logging.file.max-size"/>
|
||||
<!-- log history -->
|
||||
<springProperty scope="context" name="LOG_MAX_HISTORY" source="logging.file.max-history"/>
|
||||
<!-- pattern -->
|
||||
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%-6level] [%logger{0}:%line] - %msg%n" />
|
||||
|
||||
<!-- Console Appender -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- File Appender -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 파일경로 설정 -->
|
||||
<file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
|
||||
<!-- 출력패턴 설정 -->
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
<!-- Rolling 정책 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
|
||||
<fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log
|
||||
</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<!-- 파일당 최고 용량 kb, mb, gb -->
|
||||
<maxFileSize>${LOG_MAX-SIZE}</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
|
||||
<maxHistory>${LOG_MAX_HISTORY}</maxHistory>
|
||||
<!--<MinIndex>1</MinIndex> <MaxIndex>10</MaxIndex> -->
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<root level="${LOG_LEVEL}">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
|
||||
<!-- log4jdbc 옵션 설정 -->
|
||||
<logger name="jdbc" level="OFF" />
|
||||
<!-- 커넥션 open close 이벤트를 로그로 남긴다. -->
|
||||
<logger name="jdbc.connection" level="OFF" />
|
||||
<!-- SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다. -->
|
||||
<logger name="jdbc.sqlonly" level="OFF" />
|
||||
<!-- SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다. -->
|
||||
<logger name="jdbc.sqltiming" level="DEBUG" />
|
||||
<!-- ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다. -->
|
||||
<logger name="jdbc.audit" level="OFF" />
|
||||
<!-- ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다. -->
|
||||
<logger name="jdbc.resultset" level="OFF" />
|
||||
<!-- SQL 결과 조회된 데이터의 table을 로그로 남긴다. -->
|
||||
<logger name="jdbc.resultsettable" level="OFF" />
|
||||
</configuration>
|
@ -0,0 +1,13 @@
|
||||
package com.lsitc.fems.SpringCloudGateway;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class SpringCloudGatewayApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user