2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.fe.servlets;
23 import com.google.common.cache.Cache;
24 import com.google.common.cache.CacheBuilder;
25 import org.eclipse.jetty.client.api.Response;
26 import org.openecomp.sdc.common.api.Constants;
27 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
28 import org.openecomp.sdc.common.log.wrappers.Logger;
29 import org.openecomp.sdc.fe.config.Configuration;
30 import org.openecomp.sdc.fe.config.ConfigurationManager;
31 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
32 import org.openecomp.sdc.fe.config.PluginsConfiguration;
33 import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin;
34 import org.openecomp.sdc.fe.impl.MdcData;
35 import org.openecomp.sdc.fe.utils.BeProtocol;
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40 import java.net.MalformedURLException;
42 import java.util.concurrent.TimeUnit;
44 public class FeProxyServlet extends SSLProxyServlet {
45 private static final long serialVersionUID = 1L;
46 private static final String URL = "%s://%s%s%s";
47 private static final String ONBOARDING_CONTEXT = "/onboarding-api";
48 private static final String DCAED_CONTEXT = "/dcae-api";
49 private static final String SDC1_FE_PROXY = "/sdc1/feProxy";
50 private static final String SDC1_PLUGIN_REDIRECT = SDC1_FE_PROXY + "/plugin";
52 private static final Logger LOGGER = Logger.getLogger(FeProxyServlet.class);
53 private static final int EXPIRE_DURATION = 10;
54 private static Cache<String, MdcData> mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(EXPIRE_DURATION, TimeUnit.SECONDS).build();
58 protected String rewriteTarget(HttpServletRequest request) {
59 String originalUrl = "";
60 String redirectedUrl = "";
63 logFeRequest(request);
65 originalUrl = request.getRequestURL().toString();
66 redirectedUrl = getModifiedUrl(request);
68 } catch (MalformedURLException mue) {
69 FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
70 LOGGER.error(EcompLoggerErrorCode.DATA_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Malformed URL Exception: ", mue);
71 } catch (Exception e) {
72 FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
73 LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Unexpected FE request processing error: ", e);
76 LOGGER.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl);
82 protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) {
84 logFeResponse(request, response);
85 } catch (Exception e) {
86 FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response");
87 LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet onProxyResponseSuccess", "sdc-FE", "Unexpected FE response logging error: ", e);
89 super.onProxyResponseSuccess(request, proxyResponse, response);
92 private void logFeRequest(HttpServletRequest httpRequest) {
96 Long transactionStartTime = System.currentTimeMillis();
97 // UUID - In FE, we are supposed to get the below header from UI.
98 // We do not generate it if it's missing - BE does.
99 String uuid = httpRequest.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
100 String serviceInstanceID = httpRequest.getHeader(Constants.X_ECOMP_SERVICE_ID_HEADER);
102 if (uuid != null && uuid.length() > 0) {
103 // UserId for logging
104 String userId = httpRequest.getHeader(Constants.USER_ID_HEADER);
106 String remoteAddr = httpRequest.getRemoteAddr();
107 String localAddr = httpRequest.getLocalAddr();
109 mdcDataCache.put(uuid, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime));
111 updateMdc(uuid, serviceInstanceID, userId, remoteAddr, localAddr, null);
113 inHttpRequest(httpRequest);
116 private void logFeResponse(HttpServletRequest request, Response proxyResponse) {
117 String uuid = request.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
118 String transactionRoundTime = null;
121 MdcData mdcData = mdcDataCache.getIfPresent(uuid);
122 if (mdcData != null) {
123 Long transactionStartTime = mdcData.getTransactionStartTime();
124 if (transactionStartTime != null) { // should'n ever be null, but
125 // just to be defensive
126 transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime);
128 updateMdc(uuid, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime);
131 outHttpResponse(proxyResponse);
136 // Extracted for purpose of clear method name, for logback %M parameter
137 private void inHttpRequest(HttpServletRequest httpRequest) {
138 LOGGER.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol());
141 // Extracted for purpose of clear method name, for logback %M parameter
142 private void outHttpResponse(Response proxyResponse) {
143 LOGGER.info("SC=\"{}\"", proxyResponse.getStatus());
146 private void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) {
147 MDC.put("uuid", uuid);
148 MDC.put("serviceInstanceID", serviceInstanceID);
149 MDC.put("userId", userId);
150 MDC.put("remoteAddr", remoteAddr);
151 MDC.put("localAddr", localAddr);
152 MDC.put("timer", transactionStartTime);
157 * scan all the plugins from the configuration against the URL and the redicert path
161 private Plugin getPluginProxyForRequest(HttpServletRequest request) {
162 return getPluginConfiguration(request).getPluginsList()
165 if (plugin.getPluginProxyRedirectPath() != null && !plugin.getPluginProxyRedirectPath().isEmpty()) {
166 return request.getRequestURI().contains(SDC1_PLUGIN_REDIRECT + plugin.getPluginProxyRedirectPath());
171 .findFirst().orElse(null);
174 private String getModifiedUrl(HttpServletRequest request) throws MalformedURLException {
175 Configuration config = getConfiguration(request);
176 if (config == null) {
177 LOGGER.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet getModifiedUrl", "sdc-FE", "failed to retrieve configuration.");
178 throw new RuntimeException("failed to read FE configuration");
180 String uri = request.getRequestURI();
182 // the modify logic is as follows:
183 // - proxy ONBOARDING to the onboarding context. this is not a plugin and hardcoded
184 // - proxy DCAE to the correct context. also - not a plugin but hardcoded
185 // - proxy to the plugin according to configuration if the path is found in the plugin patterns
186 // - proxy to the catalog backend if no other proxy was found
188 if (uri.contains(ONBOARDING_CONTEXT)) {
189 uri = uri.replace(SDC1_FE_PROXY + ONBOARDING_CONTEXT, ONBOARDING_CONTEXT);
190 return getModifiedUrlString(
193 config.getOnboarding().getHostBe(),
194 config.getOnboarding().getPortBe().toString(),
195 config.getOnboarding().getProtocolBe());
197 if (uri.contains(DCAED_CONTEXT)) {
198 uri = uri.replace(SDC1_FE_PROXY + DCAED_CONTEXT, DCAED_CONTEXT);
199 return getModifiedUrlString(
203 getCatalogBePort(config),
204 config.getBeProtocol());
207 if (uri.contains(SDC1_PLUGIN_REDIRECT)) {
208 Plugin proxyPlugin = getPluginProxyForRequest(request);
209 if (proxyPlugin != null) {
210 String proxyUrlStr = (proxyPlugin.getPluginFeProxyUrl() != null) ? proxyPlugin.getPluginFeProxyUrl() : proxyPlugin.getPluginSourceUrl();
211 URL proxyUrl = new URL(proxyUrlStr);
212 uri = uri.replace(SDC1_PLUGIN_REDIRECT + proxyPlugin.getPluginProxyRedirectPath(), proxyUrl.getPath());
213 return getModifiedUrlString(request, uri, proxyUrl);
217 Plugin proxyPlugin = getPluginProxyForRequest(request);
218 if (proxyPlugin != null) {
219 String proxyUrlStr = (proxyPlugin.getPluginFeProxyUrl() != null) ? proxyPlugin.getPluginFeProxyUrl() : proxyPlugin.getPluginSourceUrl();
220 URL proxyUrl = new URL(proxyUrlStr);
221 uri = uri.replace(SDC1_FE_PROXY + proxyPlugin.getPluginProxyRedirectPath(), proxyUrl.getPath());
222 return getModifiedUrlString(request, uri, proxyUrl);
225 uri = uri.replace(SDC1_FE_PROXY, "/sdc2");
226 return getModifiedUrlString(
230 getCatalogBePort(config),
231 config.getBeProtocol());
235 private String getCatalogBePort(Configuration config) {
236 if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
237 return config.getBeHttpPort().toString();
239 return config.getBeSslPort().toString();
243 private String getModifiedUrlString(HttpServletRequest request, String uri, URL url) {
244 String queryString = getQueryString(request);
245 return String.format(URL, url.getProtocol(), url.getAuthority(), uri, queryString);
248 private String getModifiedUrlString(HttpServletRequest request, String uri, String host, String port, String protocol) {
249 String authority = getAuthority(host, port);
250 String queryString = getQueryString(request);
251 return String.format(URL, protocol, authority, uri, queryString);
254 private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) {
255 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getPluginsConfiguration();
258 private Configuration getConfiguration(HttpServletRequest request) {
259 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration();
262 private String getAuthority(String host, String port) {
267 authority = host + ":" + port;
272 private String getQueryString(HttpServletRequest request) {
273 String queryString = request.getQueryString();
274 if (queryString != null) {
275 queryString = "?" + queryString;