Access workflow from SDC in Portal
[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.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.fe.config.Configuration;
28 import org.openecomp.sdc.fe.config.ConfigurationManager;
29 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
30 import org.openecomp.sdc.fe.config.PluginsConfiguration;
31 import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin;
32 import org.openecomp.sdc.fe.impl.MdcData;
33 import org.openecomp.sdc.fe.utils.BeProtocol;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.slf4j.MDC;
37
38 import javax.servlet.http.HttpServletRequest;
39 import javax.servlet.http.HttpServletResponse;
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.util.concurrent.TimeUnit;
43
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 WORKFLOW_CONTEXT = "/wf";
50         private static final String SDC1_FE_PROXY = "/sdc1/feProxy";
51         private static final String PLUGIN_ID_WORKFLOW = "WORKFLOW";
52
53         private static final Logger log = LoggerFactory.getLogger(FeProxyServlet.class.getName());
54         private static Cache<String, MdcData> mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build();
55
56
57         @Override
58         protected String rewriteTarget(HttpServletRequest request) {
59                 String originalUrl="";
60                 String redirectedUrl = "";
61
62                 try {
63                         logFeRequest(request);
64
65                         originalUrl = request.getRequestURL().toString();
66                         redirectedUrl = getModifiedUrl(request);
67
68                 } catch(MalformedURLException mue){
69                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
70                         log.error("Unexpected FE request processing error :", mue);
71                 }
72                 catch (Exception e) {
73                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
74                         log.error("Unexpected FE request logging error :", e);
75                 }
76
77                 log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl);
78
79                 return redirectedUrl;
80         }
81
82         @Override
83         protected void onProxyResponseSuccess(HttpServletRequest request, HttpServletResponse proxyResponse, Response response) {
84                 try {
85                         logFeResponse(request, response);
86                 } catch (Exception e) {
87                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response");
88                         log.error("Unexpected FE response logging error :", e);
89                 }
90                 super.onProxyResponseSuccess(request, proxyResponse, response);
91         }
92
93         private void logFeRequest(HttpServletRequest httpRequest) {
94
95                 MDC.clear();
96
97                 Long transactionStartTime = System.currentTimeMillis();
98                 // UUID - In FE, we are supposed to get the below header from UI.
99                 // We do not generate it if it's missing - BE does.
100                 String uuid = httpRequest.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
101                 String serviceInstanceID = httpRequest.getHeader(Constants.X_ECOMP_SERVICE_ID_HEADER);
102
103                 if (uuid != null && uuid.length() > 0) {
104                         // UserId for logging
105                         String userId = httpRequest.getHeader(Constants.USER_ID_HEADER);
106
107                         String remoteAddr = httpRequest.getRemoteAddr();
108                         String localAddr = httpRequest.getLocalAddr();
109
110                         mdcDataCache.put(uuid, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime));
111
112                         updateMdc(uuid, serviceInstanceID, userId, remoteAddr, localAddr, null);
113                 }
114                 inHttpRequest(httpRequest);
115         }
116
117         private void logFeResponse(HttpServletRequest request, Response proxyResponse) {
118                 String uuid = request.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
119                 String transactionRoundTime = null;
120
121                 if (uuid != null) {
122                         MdcData mdcData = mdcDataCache.getIfPresent(uuid);
123                         if (mdcData != null) {
124                                 Long transactionStartTime = mdcData.getTransactionStartTime();
125                                 if (transactionStartTime != null) {// should'n ever be null, but
126                                         // just to be defensive
127                                         transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime);
128                                 }
129                                 updateMdc(uuid, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime);
130                         }
131                 }
132                 outHttpResponse(proxyResponse);
133
134                 MDC.clear();
135         }
136
137         // Extracted for purpose of clear method name, for logback %M parameter
138         private void inHttpRequest(HttpServletRequest httpRequest) {
139                 log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol());
140         }
141
142         // Extracted for purpose of clear method name, for logback %M parameter
143         private void outHttpResponse(Response proxyResponse) {
144                 log.info("SC=\"{}\"", proxyResponse.getStatus());
145         }
146
147         private void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) {
148                 MDC.put("uuid", uuid);
149                 MDC.put("serviceInstanceID", serviceInstanceID);
150                 MDC.put("userId", userId);
151                 MDC.put("remoteAddr", remoteAddr);
152                 MDC.put("localAddr", localAddr);
153                 MDC.put("timer", transactionStartTime);
154         }
155
156         
157         
158         private String getModifiedUrl(HttpServletRequest request) throws MalformedURLException {
159                 Configuration config = getConfiguration(request);
160                 if (config == null) {
161                         log.error("failed to retrive configuration.");
162                         throw new RuntimeException("failed to read FE configuration");
163                 }
164                 String uri = request.getRequestURI();
165                 String protocol;
166                 String host;
167                 String port;
168                 if (uri.contains(ONBOARDING_CONTEXT)){
169                         uri = uri.replace(SDC1_FE_PROXY+ONBOARDING_CONTEXT,ONBOARDING_CONTEXT);
170                         protocol = config.getOnboarding().getProtocolBe();
171                         host = config.getOnboarding().getHostBe();
172                         port = config.getOnboarding().getPortBe().toString();           
173                 }else if(uri.contains(DCAED_CONTEXT)){
174                         uri = uri.replace(SDC1_FE_PROXY+DCAED_CONTEXT,DCAED_CONTEXT);
175                         protocol = config.getBeProtocol();
176                         host = config.getBeHost();
177                         if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
178                                 port = config.getBeHttpPort().toString();
179                         } else {
180                                 port = config.getBeSslPort().toString();
181                         }
182                 }
183                 else if (uri.contains(WORKFLOW_CONTEXT)){
184                         uri = uri.replace(SDC1_FE_PROXY +WORKFLOW_CONTEXT,WORKFLOW_CONTEXT);
185                         String workflowPluginURL = getPluginConfiguration(request).getPluginsList()
186                                         .stream()
187                                         .filter(plugin -> plugin.getPluginId().equalsIgnoreCase(PLUGIN_ID_WORKFLOW))
188                                         .map(Plugin::getPluginDiscoveryUrl)
189                                         .findFirst().orElse(null);
190
191                         java.net.URL workflowURL = new URL(workflowPluginURL);
192                         protocol = workflowURL.getProtocol();
193                         host = workflowURL.getHost();
194                         port = String.valueOf(workflowURL.getPort());
195                 }
196                 else{
197                         uri = uri.replace(SDC1_FE_PROXY,"/sdc2");
198                         protocol = config.getBeProtocol();
199                         host = config.getBeHost();
200                         if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
201                                 port = config.getBeHttpPort().toString();
202                         } else {
203                                 port = config.getBeSslPort().toString();
204                         }
205                 }       
206
207                 String authority = getAuthority(host, port);
208                 String queryString = getQueryString(request);
209                 return  String.format(URL,protocol,authority,uri,queryString);
210
211         }
212
213         private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) {
214                 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getPluginsConfiguration();
215   }
216         private Configuration getConfiguration(HttpServletRequest request) {
217                 return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration();
218         }
219
220         private String getAuthority(String host, String port) {
221                 String authority;
222                 if (port==null){
223                         authority=host;
224                 }
225                 else{
226                         authority=host+":"+port;
227                 }
228                 return authority;
229         }
230
231         private String getQueryString(HttpServletRequest request) {
232                 String queryString = request.getQueryString();
233                 if (queryString != null) {
234                         queryString="?"+queryString;
235                 }
236                 else{
237                         queryString="";
238                 }
239                 return queryString;
240         }
241 }