Catalog alignment
[sdc.git] / catalog-fe / src / main / java / org / openecomp / sdc / fe / servlets / FeProxyServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.fe.servlets;
22
23 import com.google.common.annotations.VisibleForTesting;
24 import org.apache.commons.lang3.NotImplementedException;
25 import org.apache.commons.lang3.StringUtils;
26 import org.eclipse.jetty.client.api.Response;
27 import org.openecomp.sdc.common.api.Constants;
28 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
29 import org.openecomp.sdc.common.log.wrappers.Logger;
30 import org.openecomp.sdc.fe.config.Configuration;
31 import org.openecomp.sdc.fe.config.Configuration.CatalogFacadeMsConfig;
32 import org.openecomp.sdc.fe.config.ConfigurationManager;
33 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
34 import org.openecomp.sdc.fe.config.PluginsConfiguration;
35 import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin;
36 import org.openecomp.sdc.fe.impl.LogHandler;
37 import org.openecomp.sdc.fe.utils.BeProtocol;
38
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
41 import java.net.MalformedURLException;
42 import java.net.URL;
43
44 import static org.apache.commons.lang3.StringUtils.isEmpty;
45
46
47 public class FeProxyServlet extends SSLProxyServlet {
48         private static final long serialVersionUID = 1L;
49         private static final String URL = "%s://%s%s";
50         private static final String MS_URL = "%s://%s:%s";
51         private static final String ONBOARDING_CONTEXT = "/onboarding-api";
52         private static final String DCAED_CONTEXT = "/dcae-api";
53         private static final String WORKFLOW_CONTEXT = "/wf";
54         private static final String SDC1_FE_PROXY = "/sdc1/feProxy";
55         private static final String PLUGIN_ID_WORKFLOW = "WORKFLOW";
56         public static final String UUID = "uuid";
57         public static final String TRANSACTION_START_TIME = "transactionStartTime";
58         private static Logger log = Logger.getLogger(FeProxyServlet.class.getName());
59
60         private static String msUrl;
61         private static final String FACADE_PATH_IDENTIFIER = "uicache";
62         private static final String CATALOG_REQUEST_IDENTIFIER = "/v1/catalog";
63         private static final String ARCHIVE_PATH_IDENTIFIER = String.format("%s/archive/", CATALOG_REQUEST_IDENTIFIER);
64         private static final String HOME_REQUEST_IDENTIFIER = "/v1/followed";
65         @Override
66         protected String rewriteTarget(HttpServletRequest request) {
67                 String originalUrl="";
68                 String redirectedUrl = "";
69
70                 try {
71                         logFeRequest(request);
72                         originalUrl = request.getRequestURL().toString();
73
74                         Configuration config = getConfiguration(request);
75                         if (config == null) {
76                                 log.error("failed to retrieve configuration.");
77                         }
78                         if (isMsRequest(request.getRequestURL().toString())) {
79                                 redirectedUrl = redirectMsRequestToMservice(request, config);
80                         } else {
81                                 redirectedUrl = getModifiedUrl(config, getPluginConfiguration(request), request.getRequestURI(), getQueryString(request));
82                         }
83                 }
84                 catch (MalformedURLException mue) {
85                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
86                         log.error(EcompLoggerErrorCode.DATA_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Malformed URL Exception: ", mue);
87                 }
88                 catch (Exception e) {
89             log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet rewriteTarget", "sdc-FE", "Unexpected FE request processing error: ", e);
90                 }
91                 if (log.isDebugEnabled()) {
92                         log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl);
93                 }
94
95                 return redirectedUrl;
96         }
97
98         @Override
99         protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) {
100                 try {
101                         logFeResponse(request, response);
102                 } catch (Exception e) {
103                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response");
104             log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet onProxyResponseSuccess", "sdc-FE", "Unexpected FE response logging error: ", e);
105                 }
106                 super.onProxyResponseSuccess(request, proxyResponse, response);
107         }
108
109         private void logFeRequest(HttpServletRequest httpRequest){
110                 LogHandler.logFeRequest(httpRequest);
111                 inHttpRequest(httpRequest);
112         }
113
114         private void logFeResponse(HttpServletRequest request, Response proxyResponse){
115                 LogHandler.logFeResponse(request);
116                 outHttpResponse(proxyResponse);
117         }
118
119         // Extracted for purpose of clear method name, for logback %M parameter
120         private void inHttpRequest(HttpServletRequest httpRequest) {
121                 log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol());
122         }
123
124         // Extracted for purpose of clear method name, for logback %M parameter
125         private void outHttpResponse(Response proxyResponse) {
126                 log.info("SC=\"{}\"", proxyResponse.getStatus());
127         }
128
129         private String getModifiedUrl(Configuration config, PluginsConfiguration pluginConf, String uri, String queryString) throws MalformedURLException{
130                 if (config == null) {
131             log.error(EcompLoggerErrorCode.UNKNOWN_ERROR,"FeProxyServlet getModifiedUrl", "sdc-FE", "failed to retrieve configuration.");
132                         throw new RuntimeException("failed to read FE configuration");
133                 }
134                 String protocol;
135                 String host;
136                 String port;
137                 if (uri.contains(ONBOARDING_CONTEXT)){
138                         uri = uri.replace(SDC1_FE_PROXY+ONBOARDING_CONTEXT,ONBOARDING_CONTEXT);
139                         protocol = config.getOnboarding().getProtocolBe();
140                         host = config.getOnboarding().getHostBe();
141                         port = config.getOnboarding().getPortBe().toString();           
142                 }else if(uri.contains(DCAED_CONTEXT)){
143                         uri = uri.replace(SDC1_FE_PROXY+DCAED_CONTEXT,DCAED_CONTEXT);
144                         protocol = config.getBeProtocol();
145                         host = config.getBeHost();
146                         if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
147                                 port = config.getBeHttpPort().toString();
148                         } else {
149                                 port = config.getBeSslPort().toString();
150                         }
151                 }
152                 else if (uri.contains(WORKFLOW_CONTEXT)){
153                         uri = uri.replace(SDC1_FE_PROXY +WORKFLOW_CONTEXT,WORKFLOW_CONTEXT);
154                         String workflowPluginURL = pluginConf.getPluginsList()
155                                         .stream()
156                                         .filter(plugin -> plugin.getPluginId().equalsIgnoreCase(PLUGIN_ID_WORKFLOW))
157                                         .map(Plugin::getPluginDiscoveryUrl)
158                                         .findFirst().orElse(null);
159
160                         java.net.URL workflowURL = new URL(workflowPluginURL);
161                         protocol = workflowURL.getProtocol();
162                         host = workflowURL.getHost();
163                         port = String.valueOf(workflowURL.getPort());
164                 }
165                 else{
166                         uri = uri.replace(SDC1_FE_PROXY,"/sdc2");
167                         protocol = config.getBeProtocol();
168                         host = config.getBeHost();
169                         if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
170                                 port = config.getBeHttpPort().toString();
171                         } else {
172                                 port = config.getBeSslPort().toString();
173                         }
174                 }       
175
176                 String authority = getAuthority(host, port);
177                 String modifiedUrl = String.format(URL,protocol,authority,uri);
178                 if( !StringUtils.isEmpty(queryString)){
179                         modifiedUrl += "?" + queryString;
180                 }
181                  
182                 return  modifiedUrl;
183
184         }
185         @VisibleForTesting
186         String redirectMsRequestToMservice(HttpServletRequest request, Configuration config) throws MalformedURLException {
187
188                 boolean isMsToggledOn = isMsToggleOn(config);
189                 String redirectValue;
190                 if (isMsToggledOn) {
191                         redirectValue = handleMsToggleOnRedirect(request, config);
192                 } else {
193                         redirectValue = handleMsToggleOffRedirect(request, config);
194                 }
195                 return redirectValue;
196         }
197 private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) {
198                 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getPluginsConfiguration();
199   }
200         private boolean isMsToggleOn(Configuration config) {
201                 boolean toggleOn = true;
202                 final CatalogFacadeMsConfig catalogFacadeMs = config.getCatalogFacadeMs();
203                 if (catalogFacadeMs == null) {
204                         toggleOn = false;
205                         ;
206                 } else if (isEmpty(catalogFacadeMs.getHealthCheckUri())) {
207                         toggleOn = false;
208                 } else if (isEmpty(catalogFacadeMs.getHost())) {
209                         toggleOn = false;
210                 } else if (isEmpty(catalogFacadeMs.getPath())) {
211                         toggleOn = false;
212                 } else if (isEmpty(catalogFacadeMs.getProtocol())) {
213                         toggleOn = false;
214                 } else if (catalogFacadeMs.getPort() == null) {
215                         toggleOn = false;
216                 }
217                 return toggleOn;
218         }
219         private String handleMsToggleOffRedirect(HttpServletRequest request, Configuration config) throws MalformedURLException {
220                 String redirectValue;
221                 String currentURI = request.getRequestURI();
222                 if (isEmpty(request.getQueryString())) {
223                         // Catalog
224                         if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) {
225                                 String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER);
226                                 String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen");
227                                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, "excludeTypes=VFCMT&excludeTypes=Configuration");
228                         }
229                         // Home
230                         else if (currentURI.endsWith(HOME_REQUEST_IDENTIFIER)){
231                                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request));
232                         }
233                         // Archive
234                         else if (currentURI.endsWith(ARCHIVE_PATH_IDENTIFIER)) {
235                                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request));
236                         } else {
237                                 String message = String.format("facade is toggled off, Could not rediret url %s", currentURI);
238                                 log.error(message);
239                                 throw new NotImplementedException(message);
240                         }
241                 } else {
242                         // Left Pallet
243                         if (currentURI.contains("/latestversion/notabstract/metadata")) {
244                                 String nonFacadeUrl = currentURI.replace(FACADE_PATH_IDENTIFIER, "rest");
245                                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, getQueryString(request));
246                         }
247                         // Catalog with Query Params
248                         else if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) {
249                                 String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER);
250                                 String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen");
251                                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, "excludeTypes=VFCMT&excludeTypes=Configuration");
252                         } else {
253                                 String message = String.format("facade is toggled off, Could not rediret url %s with query params %s",
254                                                 currentURI, getQueryString(request));
255                                 log.error(message);
256                                 throw new NotImplementedException(message);
257                         }
258                 }
259
260                 return redirectValue;
261         }
262
263   private String handleMsToggleOnRedirect(HttpServletRequest request, Configuration config) {
264                 String currentUrl = request.getRequestURL()
265                                 .toString();
266                 if (StringUtils.isEmpty(msUrl)) {
267                         // do that only once
268                         msUrl = String.format(MS_URL, config.getCatalogFacadeMs()
269                                         .getProtocol(),
270                                         config.getCatalogFacadeMs().getHost(),
271                                         config.getCatalogFacadeMs().getPort());
272                 }
273                 StringBuilder url;
274                 String queryString;
275                 String msPath = config.getCatalogFacadeMs().getPath();
276                 if (currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER)) {
277                         url = new StringBuilder(msUrl + msPath + CATALOG_REQUEST_IDENTIFIER);
278                         queryString = "arc=true";
279                 } else {
280                         url = new StringBuilder(msUrl + currentUrl.substring(currentUrl.indexOf(msPath)));
281                         queryString = request.getQueryString();
282                 }
283                 if (queryString != null) {
284                         url.append("?").append(queryString);
285                 }
286                 if (log.isDebugEnabled()) {
287                         log.debug("Redirect catalog request to {}", url.toString());
288                 }
289                 return url.toString();
290         }
291
292         @VisibleForTesting
293         boolean isMsRequest(String currentUrl) {
294                 return currentUrl.contains(FACADE_PATH_IDENTIFIER) || currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER);
295         }
296         private Configuration getConfiguration(HttpServletRequest request) {
297                 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration();
298         }
299
300         private String getAuthority(String host, String port) {
301                 String authority;
302                 if (port==null){
303                         authority=host;
304                 }
305                 else{
306                         authority=host+":"+port;
307                 }
308                 return authority;
309         }
310         
311         private String getQueryString(HttpServletRequest request){
312                 final String queryString = request.getQueryString();
313                 return StringUtils.isEmpty(queryString) ? StringUtils.EMPTY : queryString;
314         }
315
316 }