package com.eactive.eai.adapter.service; import java.io.IOException; import java.io.StringWriter; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.apache.mina.common.ByteBuffer; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.json.simple.JSONValue; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.util.AntPathMatcher; import com.eactive.eai.adapter.AdapterGroupVO; import com.eactive.eai.adapter.AdapterVO; import com.eactive.eai.adapter.Keys; import com.eactive.eai.adapter.http.HttpMemoryLogger; import com.eactive.eai.adapter.http.HttpMethodType; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; import com.eactive.eai.adapter.http.dynamic.filter.ApiKeyExtractFilter; import com.eactive.eai.adapter.http.filter.AbstractCryptoFilter; import com.eactive.eai.common.context.ElinkTransactionContext; import com.eactive.eai.common.exception.ExceptionUtil; import com.eactive.eai.common.message.MessageType; import com.eactive.eai.common.util.CommonLib; import com.eactive.eai.common.util.JacksonUtil; import com.eactive.eai.common.util.Logger; import com.eactive.eai.common.util.TxFileLogger; import com.eactive.eai.common.util.XMLUtils; import com.eactive.eai.inbound.action.ActionFactory; import com.eactive.eai.inbound.action.RequestAction; import com.eactive.eai.inbound.processor.Processor; import com.eactive.eai.message.StandardMessageUtil; import com.eactive.eai.util.JsonPathUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @Service public class DJBApiAdapterService extends HttpAdapterServiceSupport { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); static Logger siftLogger = Logger.getLogger(Logger.LOGGER_SIFT); public static final String HEADER_GROUP = "HEADER_GROUP"; public static final String HTTP_STATUS = "HTTP_STATUS"; // jwhong // HEADER_GROUP JSON에 추가할 항목 정의, 없으면 전체 header 추가 public static final String HEADER_KEYS = "HEADER_KEYS"; public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod"; public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id"; // jwhong private ObjectMapper mapper = new ObjectMapper(); public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { int traceLevel = 0; String adptGrpName = adapterGroupVO.getName(); String adptName = adapterVO.getName(); String urlDecodeYn = httpProp.getProperty(URL_DECODE_YN, "N"); String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); String traceLevelTemp = httpProp.getProperty(TRACE_LEVEL, "0"); String relayRequestHeaderKeys = httpProp.getProperty(HEADER_KEYS); String headerGroupName = httpProp.getProperty(HEADER_GROUP); boolean isParameterType = false; String message = null; String paramValue = null; String adptMsgType = null; Properties inboundHeaderProp = getHeaders(request); transactionProp.put(INBOUND_METHOD, request.getMethod()); transactionProp.put(INBOUND_URI, request.getRequestURI()); transactionProp.put(INBOUND_QUERY_STRING, StringUtils.defaultString(request.getQueryString())); transactionProp.put(INBOUND_HEADER, inboundHeaderProp); transactionProp.put(INBOUND_EXTPARAMS, StringUtils.defaultString(request.getQueryString())); if (StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_REST) || StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) { // /api/v1/public/getUserInfo.svc String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); transactionProp.put(INBOUND_EXTURI, extUrl); } else { transactionProp.put(INBOUND_EXTURI, getExtUri(request)); } transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); transactionProp.put(API_PATH, httpProp.getProperty(API_PATH, "")); //djerp bypass transactionProp.put(INBOUND_REWRITE_PATH, getRewritePath(transactionProp.getProperty(INBOUND_EXTURI), transactionProp.getProperty(API_PATH))); transactionProp.put(INBOUND_REMOTE_ADDR, request.getRemoteAddr()); transactionProp.put(INBOUND_SCHEME, request.getScheme()); transactionProp.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, "")); transactionProp.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, "")); transactionProp.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod()); transactionProp.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, "")); transactionProp.put("BLOCK_IP", httpProp.getProperty("BLOCK_IP", "")); //djerp bypass Map pathVariables = assignPathVariables(request, adptGrpName, adptName, null, transactionProp); if (pathVariables != null) { transactionProp.put(INBOUND_PATH_VARIABLES, pathVariables); } transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong if (inboundHeaderProp.get(HEADER_NAME_CLIENT_ID) != null) { // jwhong transactionProp.put(HEADER_NAME_CLIENT_ID, inboundHeaderProp.get(HEADER_NAME_CLIENT_ID)); } transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong // //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong // transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put String inboundToken = inboundHeaderProp.getOrDefault(INBOUND_TOKEN, "").toString(); if (StringUtils.isNotBlank(inboundToken) && StringUtils.startsWith(inboundToken, "Bearer ")) { inboundToken = inboundToken.substring(7); } transactionProp.put(INBOUND_TOKEN, inboundToken); transactionProp.put(ENCRYPT_AES256_IV, httpProp.getProperty(ENCRYPT_AES256_IV, "")); //jwhong transactionProp.put(ENCRYPT_AES256_KEY, httpProp.getProperty(ENCRYPT_AES256_KEY, "")); //jwhong transactionProp.put(AbstractCryptoFilter.PROP_MODULE_NAME, httpProp.getProperty(AbstractCryptoFilter.PROP_MODULE_NAME, "")); transactionProp.put(HEADER_GROUP, headerGroupName); transactionProp.put(HEADER_KEYS, relayRequestHeaderKeys); // SEED 컬럼암호하 시 Key로 사용함 String seedkey = inboundHeaderProp.getOrDefault("x-obp-partnercode", "").toString(); ElinkTransactionContext.setSeedKey(seedkey); try { traceLevel = Integer.parseInt(traceLevelTemp); } catch (Exception e) { traceLevel = 0; } StopWatch stopWatch = new StopWatch(); stopWatch.start(); logger.debug("시작 >> encode = [" + encode + "]"); switch (HttpMethodType.getValue(request.getMethod())) { case GET: case DELETE: isParameterType = true; break; case POST: case PUT: if (StringUtils.contains(request.getContentType(), "application/x-www-form-urlencoded")) { isParameterType = true; } else if ( StringUtils.isNoneBlank(request.getQueryString()) ) { // jwhong isParameterType = true; } else { isParameterType = false; } break; default: break; } if (isParameterType) { paramValue = request.getQueryString(); transactionProp.put(INBOUND_QUERY_STRING, StringUtils.defaultString(paramValue)); // Filter에서 QueryString 검증을 위해 저장 if (paramValue == null) paramValue = ""; if (traceLevel >= 3) { HttpMemoryLogger.txlog(adptGrpName + adptName, "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(paramValue)); } // json으로 변환 StringBuilder sb = new StringBuilder(); sb.append("{"); Map paramMap = assignParameterMap(request, adptGrpName, adptName, null, transactionProp); int i = 0; for (Map.Entry entry : paramMap.entrySet()) { if (i > 0) { sb.append(","); } sb.append("\"").append(entry.getKey()).append("\":"); String[] values = entry.getValue(); if (values.length > 1) { // ["111", "222"] sb.append("["); for (int j = 0; j < values.length; j++) { if (j > 0) { sb.append(","); } sb.append("\"").append(JSONValue.escape(values[j])).append("\""); } sb.append("]"); } else { sb.append("\"").append(JSONValue.escape(values[0])).append("\""); } i++; } sb.append("}"); paramValue = sb.toString(); if (logger.isDebug()) { logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" + CommonLib.getDumpMessage(paramValue.getBytes(encode))); } } else { if (request.getContentLength() > 0) { ServletInputStream sis = request.getInputStream(); ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true); int i = 0; byte[] cbuf = new byte[1024]; while ((i = sis.read(cbuf, 0, 1024)) != -1) { if (i == 1024) { bb.put(cbuf); } else { byte[] tail = new byte[i]; System.arraycopy(cbuf, 0, tail, 0, i); bb.put(tail); } } byte[] data = new byte[bb.position()]; bb.position(0); bb.get(data); String bodyEncode = encode; String contentTypeHeader = request.getContentType(); if (StringUtils.isNotBlank(contentTypeHeader)) { try { MediaType mediaType = MediaType.parseMediaType(contentTypeHeader); if (mediaType.getCharset() != null) { bodyEncode = mediaType.getCharset().name(); } } catch (Exception ignored) {} } paramValue = new String(data, bodyEncode); if (traceLevel >= 3) { HttpMemoryLogger.txlog(adptGrpName + adptName, "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(data)); } if (logger.isDebug()) { logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" + CommonLib.getDumpMessage(data)); } } } if (paramValue == null) { // parameter가 없는 경우때문에 처리 paramValue = ""; } // 순수한 Body값을 저장을 위해 위치 변경. transactionProp.put(INBOUND_REQUEST_MESSAGE, paramValue); // paramValue가 null이 아닌 빈문자열(""," ")인 경우에 대비하여 조건 수정. // if (StringUtils.isNotBlank(paramValue)) { // jwhong decrypt // paramValue = doPreDecryption(paramValue, transactionProp, request); // } if ("Y".equals(urlDecodeYn) && isParameterType) { message = URLDecoder.decode(paramValue); } else { message = paramValue; } TxFileLogger.logTxFile(transactionProp, message, "[IN_RECV]"); if (logger.isDebug()) { String[] msgArgs = new String[2]; msgArgs[0] = adptGrpName; msgArgs[1] = message; String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs); logger.debug(resMsg); } adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); Object reqObject = assignHeaderGroupRequestHeaders(adptGrpName, adptName, message, transactionProp, request, response, adptMsgType); // 위치변경 : 가공되지 않은 Body값을 저장하기 위하여 위쪽으로 이동. // transactionProp.put(INBOUND_REQUEST_MESSAGE, message); ApiKeyExtractFilter apiKeyExtractor = new ApiKeyExtractFilter(); apiKeyExtractor.doPreFilter(adptGrpName, adptName, transactionProp.get(INBOUND_REQUEST_MESSAGE), transactionProp, request, response); Object result = service(adptGrpName, adptName, reqObject, transactionProp, request, response); // bypass만 필요 applyOutboundResponseHeaders(transactionProp, response); result = applyHeaderGroupResponseHeaders(adptGrpName, adptName, result, transactionProp, request, response, adptMsgType); if (logger.isDebug()) { logger.debug("HttpAdapterServiceRest] result " + encode + " (" + adptGrpName + ") = [" + result + "]"); } stopWatch.stop(); String syncAsyncType = transactionProp.getProperty(INBOUND_SYNC_ASYNC_TYPE); if (!"ASYN".equals(syncAsyncType) && MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)) { ObjectNode rootNode = (ObjectNode) JacksonUtil.readTree(result, mapper); JsonNode headerGroup = rootNode.get(headerGroupName); if(headerGroup != null) { for(Iterator it = headerGroup.fieldNames(); it.hasNext();) { String name = it.next(); String value = headerGroup.get(name).asText(); response.addHeader(name, value); } rootNode.remove(headerGroupName); result = rootNode; } } String strResult = null; if(result instanceof JsonNode) strResult = OBJECT_MAPPER.writeValueAsString(result); else strResult = (String) result; return strResult; } private Object assignHeaderGroupRequestHeaders(String adptGrpName, String adptName, Object message, Properties prop, HttpServletRequest request, HttpServletResponse response, String adptMsgType) throws DocumentException, IOException, Exception { // XML 지원 개발 String headerGroupName = prop.getProperty(HEADER_GROUP); String relayRequestHeaderKeys = prop.getProperty(HEADER_KEYS); if(StringUtils.isNotBlank(headerGroupName) && StringUtils.isNotBlank(relayRequestHeaderKeys)) { if (MessageType.JSON.equals(adptMsgType)) { if(message instanceof String && StringUtils.isEmpty((String)message)) message = "{}"; JsonNode jsonMessageNode = JacksonUtil.readTree(message, mapper); if (jsonMessageNode == null || !jsonMessageNode.isObject()) { jsonMessageNode = OBJECT_MAPPER.createObjectNode(); } ObjectNode jsonNode = (ObjectNode) jsonMessageNode; JsonNode childNode = jsonNode.get(headerGroupName); ObjectNode headerJson = (childNode != null && childNode.isObject()) ? (ObjectNode) childNode : OBJECT_MAPPER.createObjectNode(); if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) { for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) { String key = e.nextElement(); headerJson.put(StringUtils.lowerCase(key), request.getHeader(key)); } } else { String[] relayKeyArr = org.springframework.util.StringUtils .tokenizeToStringArray(relayRequestHeaderKeys, ","); for (String key : relayKeyArr) { String headerValue = request.getHeader(key); if (StringUtils.isNotBlank(headerValue)) { headerJson.put(StringUtils.lowerCase(key), headerValue); } } } if (!headerJson.isEmpty()) { jsonNode.set(headerGroupName, headerJson); message = jsonNode; } } else if(MessageType.XML.equals(adptMsgType)) { Document document = XMLUtils.convertXmlDocument(message); if(document != null) { Element rootElement = document.getRootElement(); Element headerElement = rootElement.element(headerGroupName); if(headerElement == null) headerElement = DocumentHelper.createElement(headerGroupName); boolean hasHeaderValues = false; if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) { for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) { String key = e.nextElement(); String value = request.getHeader(key); /* * IBK 표준안에 따라 <{key}>{value} 형태로 저장, KEY 는 소문자로 변경한다 * 대상 사이트의 표준안에 따라 작성 할 것 * * HTTP 헤더 변환 예시 * * 일반적인 HTTP 헤더 변환 예시: * Content-Type: application/json * X-Forwarded-For: 10.0.0.1 * * * original content * * application/json * 10.0.0.1 * * */ if(StringUtils.isNotBlank(value)) { Element headerItem = headerElement.addElement(key); headerItem.setText(value); hasHeaderValues = true; } } } else { String[] relayKeyArr = org.springframework.util.StringUtils .tokenizeToStringArray(relayRequestHeaderKeys, ","); for (String key : relayKeyArr) { String headerValue = request.getHeader(key); if (StringUtils.isNotBlank(headerValue)) { String value = request.getHeader(key); String keyName = StringUtils.lowerCase(key); Element headerItem = headerElement.addElement(keyName); headerItem.setText(value); hasHeaderValues = true; } } } if (hasHeaderValues) { rootElement.add(headerElement); OutputFormat format = OutputFormat.createPrettyPrint(); StringWriter writer = new StringWriter(); XMLWriter xmlWriter = new XMLWriter(writer, format); xmlWriter.write(document); message = writer.toString(); } } } } if (message == null) { message = ""; } // XML 지원 개발 return message; } /** * HttpClientAdapterServiceBypass.assignRelayDataToInbound() 에서 * transactionProp에 저장한 OUTBOUND_RESPONSE_HEADERS를 response에 적용한다. */ @SuppressWarnings("unchecked") private void applyOutboundResponseHeaders(Properties transactionProp, HttpServletResponse response) { Map outboundPropertyMap = (Map) transactionProp.get(OUTBOUND_PROPERTY_MAP); if (outboundPropertyMap == null) { return; } Properties headerProp = (Properties) outboundPropertyMap.get(OUTBOUND_RESPONSE_HEADERS); if (headerProp == null) { return; } String[] hopByHopHeaders = { "Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "TE", "Trailers", "Transfer-Encoding", "Upgrade" }; for (Map.Entry entry : headerProp.entrySet()) { String key = (String) entry.getKey(); String value = (String) entry.getValue(); if (StringUtils.equalsAnyIgnoreCase(key, hopByHopHeaders)) { continue; } if (StringUtils.equalsIgnoreCase(key, HttpHeaders.CONTENT_LENGTH)) { continue; } if (StringUtils.equalsIgnoreCase(key, HTTP_STATUS)) { if (StringUtils.isNotBlank(value)) { try { response.setStatus(Integer.parseInt(value)); } catch (NumberFormatException ex) { // ignore } } continue; } response.addHeader(key, value); } } private Object applyHeaderGroupResponseHeaders(String adptGrpName, String adptName, Object resultMessage, Properties prop, HttpServletRequest request, HttpServletResponse response, String adptMsgType) throws Exception { // body headergroup -> http header 세팅 String headerGroupName = prop.getProperty(HEADER_GROUP); if (StringUtils.isNotBlank(headerGroupName)) { if (resultMessage instanceof Node) { adptMsgType = MessageType.XML; } else if (resultMessage instanceof String) { String strMessage = (String) resultMessage; if (StringUtils.startsWith(strMessage, "<")) { adptMsgType = MessageType.XML; } } else if (resultMessage instanceof byte[]) { String strMessage = new String((byte[]) resultMessage); if (StringUtils.startsWith(strMessage, "<")) { adptMsgType = MessageType.XML; } } if (MessageType.JSON.equals(adptMsgType)) { JsonNode jsonNode = JacksonUtil.readTree(resultMessage, OBJECT_MAPPER); // 또는 // objectMapper.readTree(resultMessage) JsonNode headerGroup = jsonNode.get(headerGroupName); if (headerGroup != null && !headerGroup.isNull()) { Iterator> fieldIterator = headerGroup.fields(); while (fieldIterator.hasNext()) { Map.Entry fieldEntry = fieldIterator.next(); JsonNode valueNode = fieldEntry.getValue(); logger.info("header group entry : {} , {}", fieldEntry.getKey(), valueNode); if (valueNode.isTextual()) { String value = valueNode.asText(); if (StringUtils.equalsIgnoreCase(fieldEntry.getKey(), "content-type")) { logger.debug("set content-type {}: {}", fieldEntry.getKey(), value); response.setContentType(value); } else if (StringUtils.equalsIgnoreCase(fieldEntry.getKey(), HttpHeaders.CONTENT_LENGTH)) { logger.debug("skip content-length {}: {}", fieldEntry.getKey(), value); continue; } else { logger.debug("add header {}: {}", fieldEntry.getKey(), value); response.addHeader(fieldEntry.getKey(), value); } } else { logger.info("fieldEntry value is not String. {}", valueNode); } } } else { logger.info("headerGroup is null"); } ((ObjectNode) jsonNode).remove(headerGroupName); return jsonNode; } else if(MessageType.XML.equals(adptMsgType)) { Document document = XMLUtils.convertXmlDocument(resultMessage); if(document != null) { Element rootElement = document.getRootElement(); Element headerGroupElement = rootElement.element(headerGroupName); if(headerGroupElement != null) { //헤더그룹의 모든 하위 엘리먼트를 HTTP 응답 헤더로 설정 for(Iterator it = headerGroupElement.elementIterator(); it.hasNext();) { Element headerElement = it.next(); String name = headerElement.getName(); String value = headerElement.getTextTrim(); if(StringUtils.isNoneBlank(value)) { if(StringUtils.equalsIgnoreCase(name, "content-type")) { logger.debug("set content-type {}: {}", name, value); response.setContentType(value); } else if(StringUtils.equalsIgnoreCase(name, "content-length")) { logger.debug("skip content-length {}: {}", name, value); continue; } else { logger.debug("add header {}: {}", name, value); response.addHeader(name, value); } } else { logger.info("value is not String. {}", value); } } } else { logger.info("headerGroup is null"); } // 헤더그룹 삭제 rootElement.remove(headerGroupElement); return document.asXML(); } } } else { logger.info("headerGroupName is blank"); } return (String)resultMessage; } private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, Object requestBytes, Properties prop) { // PathVariable 체크 if (StringUtils.equalsAnyIgnoreCase(request.getMethod(), HttpMethod.GET.name(), HttpMethod.DELETE.name()) && StringUtils.isBlank(request.getQueryString())) { try { String actionName = prop.getProperty(Processor.REQUEST_ACTION); RequestAction action = ActionFactory.createAction(actionName); action.setAdapterInfo(adptGrpName, adptName, prop); String[] keys = action.perform(requestBytes); String requestPath = keys[0]; // PathVariable 지원 추가 String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName); if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) { Map paramMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath, requestPath); if (paramMap != null && paramMap.size() > 0) { Map returnMap = new HashMap<>(); for (String key : paramMap.keySet()) { if (StringUtils.equalsIgnoreCase(key, "method")) { continue; } returnMap.put(key, new String[] { paramMap.get(key) }); } return returnMap; } } } catch (Exception e) { logger.error(e.getMessage()); } } return request.getParameterMap(); } private String getRewritePath(String extUri, String basePath) { return StringUtils.removeStart(extUri, StringUtils.removeEnd(basePath, "/")); } private Map assignPathVariables(HttpServletRequest request, String adptGrpName, String adptName, Object requestBytes, Properties prop) { Map variablesMap = null; // QueryString 있을때는 체크(X) if (StringUtils.isBlank(request.getQueryString())) { try { String actionName = prop.getProperty(Processor.REQUEST_ACTION); RequestAction action = ActionFactory.createAction(actionName); action.setAdapterInfo(adptGrpName, adptName, prop); String[] keys = action.perform(requestBytes); String requestPath = keys[0]; // PathVariable 지원 추가 String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName); if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) { variablesMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath, requestPath); } } catch (Exception e) { logger.error(e.getMessage()); } } return variablesMap; } private Properties getHeaders(HttpServletRequest request) { Properties prop = new Properties(); Enumeration headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = headerNames.nextElement(); // 동일 이름의 헤더가 여러 개인 경우 콤마로 합침 (RFC 7230) Enumeration values = request.getHeaders(key); StringBuilder sb = new StringBuilder(); while (values.hasMoreElements()) { if (sb.length() > 0) sb.append(", "); sb.append(values.nextElement()); } prop.setProperty(key.toLowerCase(), sb.toString()); } return prop; } private String getExtUri(HttpServletRequest request) { String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), ""); String uri = getExtUri(orgUri, 3); if (uri != null && uri.trim().length() > 0) { return "/" + uri; } else { return ""; } } private static String getExtUri(String url, int length) { String[] urls = url.split("/"); List newUrls = new ArrayList<>(); Collections.addAll(newUrls, urls); return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/"); } @Override @Deprecated public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) { } /** * HTTP 요청에서 클라이언트 IP를 추출합니다. * X-Forwarded-For 헤더가 있는 경우 이를 우선적으로 사용하고, * 없는 경우 remoteAddr을 사용합니다. */ private String getClientIp(HttpServletRequest request) { String ipAddress = request.getHeader("X-Forwarded-For"); if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("WL-Proxy-Client-IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("HTTP_CLIENT_IP"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); } return ipAddress; } private String assignApiId(String adptGrpName, String adptName, Object message, Properties prop, HttpServletRequest request) { String apiId = null; try { String actionName = prop.getProperty(Processor.REQUEST_ACTION); RequestAction action = ActionFactory.createAction(actionName); action.setAdapterInfo(adptGrpName, adptName, prop); String[] keys = action.perform(message); apiId = keys[0]; // PathVariable 지원 추가 apiId = StandardMessageUtil.getMatchedKey(apiId, actionName); } catch (Exception e) { logger.error(e.getMessage()); } // // header 에서 확보 // String apiId = request.getHeader(HEADER_NAME_API_CODE); // if (StringUtils.isBlank(apiId)) { // // url에서 확보 // // /ONLWeb/api/v1/public/getUserInfo.svc/ // apiId = request.getRequestURI(); // // /ONLWeb/api/v1/public/getUserInfo.svc // apiId = StringUtils.removeEnd(apiId, "/"); // // getUserInfo.svc // apiId = StringUtils.substringAfterLast(apiId, "/"); // } return apiId; } }