diff options
Diffstat (limited to 'catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java')
-rw-r--r-- | catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java | 477 |
1 files changed, 278 insertions, 199 deletions
diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java index 1c7b174c57..3ea660abbe 100644 --- a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,218 +20,297 @@ package org.openecomp.sdc.fe.servlets; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; +import com.google.common.annotations.VisibleForTesting; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.client.api.Response; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.Configuration.CatalogFacadeMsConfig; import org.openecomp.sdc.fe.config.ConfigurationManager; import org.openecomp.sdc.fe.config.FeEcompErrorManager; import org.openecomp.sdc.fe.config.PluginsConfiguration; import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin; -import org.openecomp.sdc.fe.impl.MdcData; +import org.openecomp.sdc.fe.impl.LogHandler; import org.openecomp.sdc.fe.utils.BeProtocol; -import org.slf4j.MDC; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.MalformedURLException; import java.net.URL; -import java.util.concurrent.TimeUnit; + +import static org.apache.commons.lang3.StringUtils.isEmpty; + public class FeProxyServlet extends SSLProxyServlet { - private static final long serialVersionUID = 1L; - private static final String URL = "%s://%s%s%s"; - private static final String ONBOARDING_CONTEXT = "/onboarding-api"; - private static final String DCAED_CONTEXT = "/dcae-api"; - private static final String WORKFLOW_CONTEXT = "/wf"; - private static final String SDC1_FE_PROXY = "/sdc1/feProxy"; - private static final String PLUGIN_ID_WORKFLOW = "WORKFLOW"; - - private static final Logger LOGGER = Logger.getLogger(FeProxyServlet.class); - private static final int EXPIRE_DURATION = 10; - private static Cache<String, MdcData> mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(EXPIRE_DURATION, TimeUnit.SECONDS).build(); - - - @Override - protected String rewriteTarget(HttpServletRequest request) { - String originalUrl = ""; - String redirectedUrl = ""; - - try { - logFeRequest(request); - - originalUrl = request.getRequestURL().toString(); - redirectedUrl = getModifiedUrl(request); - - } catch (MalformedURLException mue) { - FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request"); - LOGGER.error(EcompLoggerErrorCode.DATA_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Malformed URL Exception: ", mue); - } catch (Exception e) { - FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request"); - LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Unexpected FE request processing error: ", e); - } - - LOGGER.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl); - - return redirectedUrl; - } - - @Override - protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) { - try { - logFeResponse(request, response); - } catch (Exception e) { - FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response"); - LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet onProxyResponseSuccess", "sdc-FE", "Unexpected FE response logging error: ", e); - } - super.onProxyResponseSuccess(request, proxyResponse, response); - } - - private void logFeRequest(HttpServletRequest httpRequest) { - - MDC.clear(); - - Long transactionStartTime = System.currentTimeMillis(); - // UUID - In FE, we are supposed to get the below header from UI. - // We do not generate it if it's missing - BE does. - String uuid = httpRequest.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER); - String serviceInstanceID = httpRequest.getHeader(Constants.X_ECOMP_SERVICE_ID_HEADER); - - if (uuid != null && uuid.length() > 0) { - // UserId for logging - String userId = httpRequest.getHeader(Constants.USER_ID_HEADER); - - String remoteAddr = httpRequest.getRemoteAddr(); - String localAddr = httpRequest.getLocalAddr(); - - mdcDataCache.put(uuid, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime)); - - updateMdc(uuid, serviceInstanceID, userId, remoteAddr, localAddr, null); - } - inHttpRequest(httpRequest); - } - - private void logFeResponse(HttpServletRequest request, Response proxyResponse) { - String uuid = request.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER); - String transactionRoundTime = null; - - if (uuid != null) { - MdcData mdcData = mdcDataCache.getIfPresent(uuid); - if (mdcData != null) { - Long transactionStartTime = mdcData.getTransactionStartTime(); - if (transactionStartTime != null) { // should'n ever be null, but - // just to be defensive - transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime); - } - updateMdc(uuid, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime); - } - } - outHttpResponse(proxyResponse); - - MDC.clear(); - } - - // Extracted for purpose of clear method name, for logback %M parameter - private void inHttpRequest(HttpServletRequest httpRequest) { - LOGGER.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol()); - } - - // Extracted for purpose of clear method name, for logback %M parameter - private void outHttpResponse(Response proxyResponse) { - LOGGER.info("SC=\"{}\"", proxyResponse.getStatus()); - } - - private void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) { - MDC.put("uuid", uuid); - MDC.put("serviceInstanceID", serviceInstanceID); - MDC.put("userId", userId); - MDC.put("remoteAddr", remoteAddr); - MDC.put("localAddr", localAddr); - MDC.put("timer", transactionStartTime); - } - - - private String getModifiedUrl(HttpServletRequest request) throws MalformedURLException { - Configuration config = getConfiguration(request); - if (config == null) { - LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet getModifiedUrl", "sdc-FE", "failed to retrieve configuration."); - throw new RuntimeException("failed to read FE configuration"); - } - String uri = request.getRequestURI(); - String protocol; - String host; - String port; - if (uri.contains(ONBOARDING_CONTEXT)) { - uri = uri.replace(SDC1_FE_PROXY + ONBOARDING_CONTEXT, ONBOARDING_CONTEXT); - protocol = config.getOnboarding().getProtocolBe(); - host = config.getOnboarding().getHostBe(); - port = config.getOnboarding().getPortBe().toString(); - } else if (uri.contains(DCAED_CONTEXT)) { - uri = uri.replace(SDC1_FE_PROXY + DCAED_CONTEXT, DCAED_CONTEXT); - protocol = config.getBeProtocol(); - host = config.getBeHost(); - if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) { - port = config.getBeHttpPort().toString(); - } else { - port = config.getBeSslPort().toString(); - } - } else if (uri.contains(WORKFLOW_CONTEXT)) { - String workflowPluginURL = getPluginConfiguration(request).getPluginsList() - .stream() - .filter(plugin -> plugin.getPluginId().equalsIgnoreCase(PLUGIN_ID_WORKFLOW)) - .map(Plugin::getPluginDiscoveryUrl) - .findFirst().orElse(null); - - java.net.URL workflowURL = new URL(workflowPluginURL); - protocol = workflowURL.getProtocol(); - host = workflowURL.getHost(); - port = String.valueOf(workflowURL.getPort()); - uri = uri.replace(SDC1_FE_PROXY + WORKFLOW_CONTEXT, workflowURL.getPath() + WORKFLOW_CONTEXT); - } else { - uri = uri.replace(SDC1_FE_PROXY, "/sdc2"); - protocol = config.getBeProtocol(); - host = config.getBeHost(); - if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) { - port = config.getBeHttpPort().toString(); - } else { - port = config.getBeSslPort().toString(); - } - } - - String authority = getAuthority(host, port); - String queryString = getQueryString(request); - return String.format(URL, protocol, authority, uri, queryString); - - } - - private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) { - return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getPluginsConfiguration(); - } - - private Configuration getConfiguration(HttpServletRequest request) { - return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration(); - } - - private String getAuthority(String host, String port) { - String authority; - if (port == null) { - authority = host; - } else { - authority = host + ":" + port; - } - return authority; - } - - private String getQueryString(HttpServletRequest request) { - String queryString = request.getQueryString(); - if (queryString != null) { - queryString = "?" + queryString; - } else { - queryString = ""; - } - return queryString; - } + private static final long serialVersionUID = 1L; + private static final String URL = "%s://%s%s"; + private static final String MS_URL = "%s://%s:%s"; + private static final String ONBOARDING_CONTEXT = "/onboarding-api"; + private static final String DCAED_CONTEXT = "/dcae-api"; + private static final String WORKFLOW_CONTEXT = "/wf"; + private static final String SDC1_FE_PROXY = "/sdc1/feProxy"; + private static final String PLUGIN_ID_WORKFLOW = "WORKFLOW"; + public static final String UUID = "uuid"; + public static final String TRANSACTION_START_TIME = "transactionStartTime"; + private static Logger log = Logger.getLogger(FeProxyServlet.class.getName()); + + private static String msUrl; + private static final String FACADE_PATH_IDENTIFIER = "uicache"; + private static final String CATALOG_REQUEST_IDENTIFIER = "/v1/catalog"; + private static final String ARCHIVE_PATH_IDENTIFIER = String.format("%s/archive/", CATALOG_REQUEST_IDENTIFIER); + private static final String HOME_REQUEST_IDENTIFIER = "/v1/followed"; + @Override + protected String rewriteTarget(HttpServletRequest request) { + String originalUrl=""; + String redirectedUrl = ""; + + try { + logFeRequest(request); + originalUrl = request.getRequestURL().toString(); + + Configuration config = getConfiguration(request); + if (config == null) { + log.error("failed to retrieve configuration."); + } + if (isMsRequest(request.getRequestURL().toString())) { + redirectedUrl = redirectMsRequestToMservice(request, config); + } else { + redirectedUrl = getModifiedUrl(config, getPluginConfiguration(request), request.getRequestURI(), getQueryString(request)); + } + } + catch (MalformedURLException mue) { + FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request"); + log.error(EcompLoggerErrorCode.DATA_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Malformed URL Exception: ", mue); + } + catch (Exception e) { + log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet rewriteTarget", "sdc-FE", "Unexpected FE request processing error: ", e); + } + if (log.isDebugEnabled()) { + log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl); + } + + return redirectedUrl; + } + + @Override + protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) { + try { + logFeResponse(request, response); + } catch (Exception e) { + FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response"); + log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet onProxyResponseSuccess", "sdc-FE", "Unexpected FE response logging error: ", e); + } + super.onProxyResponseSuccess(request, proxyResponse, response); + } + + private void logFeRequest(HttpServletRequest httpRequest){ + LogHandler.logFeRequest(httpRequest); + inHttpRequest(httpRequest); + } + + private void logFeResponse(HttpServletRequest request, Response proxyResponse){ + LogHandler.logFeResponse(request); + outHttpResponse(proxyResponse); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void inHttpRequest(HttpServletRequest httpRequest) { + log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol()); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void outHttpResponse(Response proxyResponse) { + log.info("SC=\"{}\"", proxyResponse.getStatus()); + } + + private String getModifiedUrl(Configuration config, PluginsConfiguration pluginConf, String uri, String queryString) throws MalformedURLException{ + if (config == null) { + log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet getModifiedUrl", "sdc-FE", "failed to retrieve configuration."); + throw new RuntimeException("failed to read FE configuration"); + } + String protocol; + String host; + String port; + if (uri.contains(ONBOARDING_CONTEXT)){ + uri = uri.replace(SDC1_FE_PROXY+ONBOARDING_CONTEXT,ONBOARDING_CONTEXT); + protocol = config.getOnboarding().getProtocolBe(); + host = config.getOnboarding().getHostBe(); + port = config.getOnboarding().getPortBe().toString(); + }else if(uri.contains(DCAED_CONTEXT)){ + uri = uri.replace(SDC1_FE_PROXY+DCAED_CONTEXT,DCAED_CONTEXT); + protocol = config.getBeProtocol(); + host = config.getBeHost(); + if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) { + port = config.getBeHttpPort().toString(); + } else { + port = config.getBeSslPort().toString(); + } + } + else if (uri.contains(WORKFLOW_CONTEXT)){ + uri = uri.replace(SDC1_FE_PROXY +WORKFLOW_CONTEXT,WORKFLOW_CONTEXT); + String workflowPluginURL = pluginConf.getPluginsList() + .stream() + .filter(plugin -> plugin.getPluginId().equalsIgnoreCase(PLUGIN_ID_WORKFLOW)) + .map(Plugin::getPluginDiscoveryUrl) + .findFirst().orElse(null); + + java.net.URL workflowURL = new URL(workflowPluginURL); + protocol = workflowURL.getProtocol(); + host = workflowURL.getHost(); + port = String.valueOf(workflowURL.getPort()); + } + else{ + uri = uri.replace(SDC1_FE_PROXY,"/sdc2"); + protocol = config.getBeProtocol(); + host = config.getBeHost(); + if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) { + port = config.getBeHttpPort().toString(); + } else { + port = config.getBeSslPort().toString(); + } + } + + String authority = getAuthority(host, port); + String modifiedUrl = String.format(URL,protocol,authority,uri); + if( !StringUtils.isEmpty(queryString)){ + modifiedUrl += "?" + queryString; + } + + return modifiedUrl; + + } + @VisibleForTesting + String redirectMsRequestToMservice(HttpServletRequest request, Configuration config) throws MalformedURLException { + + boolean isMsToggledOn = isMsToggleOn(config); + String redirectValue; + if (isMsToggledOn) { + redirectValue = handleMsToggleOnRedirect(request, config); + } else { + redirectValue = handleMsToggleOffRedirect(request, config); + } + return redirectValue; + } +private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) { + return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getPluginsConfiguration(); + } + private boolean isMsToggleOn(Configuration config) { + boolean toggleOn = true; + final CatalogFacadeMsConfig catalogFacadeMs = config.getCatalogFacadeMs(); + if (catalogFacadeMs == null) { + toggleOn = false; + ; + } else if (isEmpty(catalogFacadeMs.getHealthCheckUri())) { + toggleOn = false; + } else if (isEmpty(catalogFacadeMs.getHost())) { + toggleOn = false; + } else if (isEmpty(catalogFacadeMs.getPath())) { + toggleOn = false; + } else if (isEmpty(catalogFacadeMs.getProtocol())) { + toggleOn = false; + } else if (catalogFacadeMs.getPort() == null) { + toggleOn = false; + } + return toggleOn; + } + private String handleMsToggleOffRedirect(HttpServletRequest request, Configuration config) throws MalformedURLException { + String redirectValue; + String currentURI = request.getRequestURI(); + if (isEmpty(request.getQueryString())) { + // Catalog + if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) { + String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER); + String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen"); + redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, "excludeTypes=VFCMT&excludeTypes=Configuration"); + } + // Home + else if (currentURI.endsWith(HOME_REQUEST_IDENTIFIER)){ + redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request)); + } + // Archive + else if (currentURI.endsWith(ARCHIVE_PATH_IDENTIFIER)) { + redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request)); + } else { + String message = String.format("facade is toggled off, Could not rediret url %s", currentURI); + log.error(message); + throw new NotImplementedException(message); + } + } else { + // Left Pallet + if (currentURI.contains("/latestversion/notabstract/metadata")) { + String nonFacadeUrl = currentURI.replace(FACADE_PATH_IDENTIFIER, "rest"); + redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, getQueryString(request)); + } + // Catalog with Query Params + else if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) { + String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER); + String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen"); + redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, "excludeTypes=VFCMT&excludeTypes=Configuration"); + } else { + String message = String.format("facade is toggled off, Could not rediret url %s with query params %s", + currentURI, getQueryString(request)); + log.error(message); + throw new NotImplementedException(message); + } + } + + return redirectValue; + } + + private String handleMsToggleOnRedirect(HttpServletRequest request, Configuration config) { + String currentUrl = request.getRequestURL() + .toString(); + if (StringUtils.isEmpty(msUrl)) { + // do that only once + msUrl = String.format(MS_URL, config.getCatalogFacadeMs() + .getProtocol(), + config.getCatalogFacadeMs().getHost(), + config.getCatalogFacadeMs().getPort()); + } + StringBuilder url; + String queryString; + String msPath = config.getCatalogFacadeMs().getPath(); + if (currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER)) { + url = new StringBuilder(msUrl + msPath + CATALOG_REQUEST_IDENTIFIER); + queryString = "arc=true"; + } else { + url = new StringBuilder(msUrl + currentUrl.substring(currentUrl.indexOf(msPath))); + queryString = request.getQueryString(); + } + if (queryString != null) { + url.append("?").append(queryString); + } + if (log.isDebugEnabled()) { + log.debug("Redirect catalog request to {}", url.toString()); + } + return url.toString(); + } + + @VisibleForTesting + boolean isMsRequest(String currentUrl) { + return currentUrl.contains(FACADE_PATH_IDENTIFIER) || currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER); + } + private Configuration getConfiguration(HttpServletRequest request) { + return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration(); + } + + private String getAuthority(String host, String port) { + String authority; + if (port==null){ + authority=host; + } + else{ + authority=host+":"+port; + } + return authority; + } + + private String getQueryString(HttpServletRequest request){ + final String queryString = request.getQueryString(); + return StringUtils.isEmpty(queryString) ? StringUtils.EMPTY : queryString; + } + } |