Sync Integ to Master
[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 java.net.URI;
24 import java.util.concurrent.TimeUnit;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.eclipse.jetty.client.api.Response;
30 import org.openecomp.sdc.common.api.Constants;
31 import org.openecomp.sdc.common.config.EcompErrorName;
32 import org.openecomp.sdc.fe.config.Configuration;
33 import org.openecomp.sdc.fe.config.ConfigurationManager;
34 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.slf4j.MDC;
38
39 import com.google.common.cache.Cache;
40 import com.google.common.cache.CacheBuilder;
41
42 public class FeProxyServlet extends SSLProxyServlet {
43         private static final long serialVersionUID = 1L;
44         private static final String URL = "%s://%s:%s%s";
45         private static Logger log = LoggerFactory.getLogger(FeProxyServlet.class.getName());
46         private static Cache<String, MdcData> mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build();
47
48         @Override
49         public URI rewriteURI(HttpServletRequest request) {
50                 try {
51                         logFeRequest(request);
52                 } catch (Exception e) {
53                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
54                         log.error("Unexpected FE request logging error :", e);
55                 }
56                 String originalUrl = request.getRequestURL().toString();
57                 String redirectedUrl = getModifiedUrl(request);
58
59                 log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl);
60
61                 return URI.create(redirectedUrl);
62         }
63
64         @Override
65         protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse) {
66                 try {
67                         logFeResponse(request, proxyResponse);
68                 } catch (Exception e) {
69                         FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response");
70                         log.error("Unexpected FE response logging error :", e);
71                 }
72                 super.onResponseSuccess(request, response, proxyResponse);
73         }
74
75         private void logFeRequest(HttpServletRequest httpRequest) {
76
77                 MDC.clear();
78
79                 Long transactionStartTime = System.currentTimeMillis();
80                 // UUID - In FE, we are supposed to get the below header from UI.
81                 // We do not generate it if it's missing - BE does.
82                 String uuid = httpRequest.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
83                 String serviceInstanceID = httpRequest.getHeader(Constants.X_ECOMP_SERVICE_ID_HEADER);
84
85                 if (uuid != null && uuid.length() > 0) {
86                         // UserId for logging
87                         String userId = httpRequest.getHeader(Constants.USER_ID_HEADER);
88
89                         String remoteAddr = httpRequest.getRemoteAddr();
90                         String localAddr = httpRequest.getLocalAddr();
91
92                         mdcDataCache.put(uuid, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime));
93
94                         updateMdc(uuid, serviceInstanceID, userId, remoteAddr, localAddr, null);
95                 }
96                 inHttpRequest(httpRequest);
97         }
98
99         private void logFeResponse(HttpServletRequest request, Response proxyResponse) {
100                 String uuid = request.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER);
101                 String transactionRoundTime = null;
102
103                 if (uuid != null) {
104                         MdcData mdcData = mdcDataCache.getIfPresent(uuid);
105                         if (mdcData != null) {
106                                 Long transactionStartTime = mdcData.getTransactionStartTime();
107                                 if (transactionStartTime != null) {// should'n ever be null, but
108                                                                                                         // just to be defensive
109                                         transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime);
110                                 }
111                                 updateMdc(uuid, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime);
112                         }
113                 }
114                 outHttpResponse(proxyResponse);
115
116                 MDC.clear();
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 void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) {
130                 MDC.put("uuid", uuid);
131                 MDC.put("serviceInstanceID", serviceInstanceID);
132                 MDC.put("userId", userId);
133                 MDC.put("remoteAddr", remoteAddr);
134                 MDC.put("localAddr", localAddr);
135                 MDC.put("timer", transactionStartTime);
136         }
137
138         private class MdcData {
139                 private String serviceInstanceID;
140                 private String userId;
141                 private String remoteAddr;
142                 private String localAddr;
143                 private Long transactionStartTime;
144
145                 public MdcData(String serviceInstanceID, String userId, String remoteAddr, String localAddr, Long transactionStartTime) {
146                         super();
147                         this.serviceInstanceID = serviceInstanceID;
148                         this.userId = userId;
149                         this.remoteAddr = remoteAddr;
150                         this.localAddr = localAddr;
151                         this.transactionStartTime = transactionStartTime;
152                 }
153
154                 public Long getTransactionStartTime() {
155                         return transactionStartTime;
156                 }
157
158                 public String getUserId() {
159                         return userId;
160                 }
161
162                 public String getRemoteAddr() {
163                         return remoteAddr;
164                 }
165
166                 public String getLocalAddr() {
167                         return localAddr;
168                 }
169
170                 public String getServiceInstanceID() {
171                         return serviceInstanceID;
172                 }
173         }
174
175         public String getModifiedUrl(HttpServletRequest request) {
176
177                 Configuration config = getConfiguration(request);
178                 if (config == null) {
179                         log.error("failed to retrive configuration.");
180                 }
181                 String scheme = config.getBeProtocol();
182                 String uri = request.getRequestURI().toString();
183                 StringBuilder url = new StringBuilder();
184                 url.append(scheme).append("://").append(config.getBeHost());
185                 url.append(":");
186                 if (config.getBeProtocol().equals(BE_PROTOCOL.HTTP.getProtocolName())) {
187                         url.append(config.getBeHttpPort());
188                 } else {
189                         url.append(config.getBeSslPort());
190                 }
191                 url.append(uri);
192                 String queryString = request.getQueryString(); // d=789
193                 if (queryString != null) {
194                         url.append("?").append(queryString);
195                 }
196
197                 String redirectedUrl = url.toString();
198                 String onboardingForwardContext = config.getOnboardingForwardContext();
199                 if (onboardingForwardContext == null || onboardingForwardContext.isEmpty()) {
200                         onboardingForwardContext = "/onboarding-api";
201                 }
202                 redirectedUrl = redirectedUrl.replace("/sdc1/feProxy/dcae-api", "/dcae");
203                 redirectedUrl = redirectedUrl.replace("/sdc1/feProxy/onboarding-api", onboardingForwardContext);
204                 redirectedUrl = redirectedUrl.replace("/sdc1/feProxy", "/sdc2");
205                 return redirectedUrl;
206
207         }
208
209         private Configuration getConfiguration(HttpServletRequest request) {
210                 Configuration config = ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration();
211                 return config;
212         }
213 }