add to AAI headers in request and metric log
[vid.git] / vid-app-common / src / main / java / org / onap / vid / aai / util / AAIRestInterface.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 - 2019 Nokia. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.vid.aai.util;
22
23
24 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import java.io.UnsupportedEncodingException;
28 import java.net.URI;
29 import java.net.URLEncoder;
30 import java.util.Optional;
31 import java.util.UUID;
32 import java.util.function.Supplier;
33 import javax.ws.rs.client.Client;
34 import javax.ws.rs.client.Entity;
35 import javax.ws.rs.client.Invocation;
36 import javax.ws.rs.core.MediaType;
37 import javax.ws.rs.core.Response;
38 import org.apache.commons.lang3.StringUtils;
39 import org.apache.commons.lang3.exception.ExceptionUtils;
40 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
41 import org.onap.vid.aai.ExceptionWithRequestInfo;
42 import org.onap.vid.aai.ResponseWithRequestInfo;
43 import org.onap.vid.aai.exceptions.InvalidPropertyException;
44 import org.onap.vid.logging.VidMetricLogClientFilter;
45 import org.onap.vid.utils.Logging;
46 import org.onap.vid.utils.Unchecked;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.http.HttpMethod;
49
50
51 /**
52  * The Class AAIRestInterface.
53  */
54 public class AAIRestInterface {
55
56     /** The logger. */
57     protected EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AAIRestInterface.class);
58
59     protected final EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("aai");
60
61     /** The client. */
62     private Client client = null;
63
64     /** The rest srvr base URL. */
65     private String restSrvrBaseURL;
66
67     @Autowired
68     protected HttpsAuthClient httpsAuthClientFactory;
69     private final ServletRequestHelper servletRequestHelper;
70     private final SystemPropertyHelper systemPropertyHelper;
71     protected final Logging loggingService;
72
73     protected static final String START_STRING = " start";
74     protected static final String TRANSACTION_ID_HEADER = "X-TransactionId";
75     protected static final String FROM_APP_ID_HEADER = "X-FromAppId";
76     protected static final String SUCCESSFUL_API_MESSAGE = " REST api call was successful!";
77     protected static final String URL_DECLARATION = ", url=";
78
79     public AAIRestInterface(HttpsAuthClient httpsAuthClientFactory,
80         ServletRequestHelper servletRequestHelper,
81         SystemPropertyHelper systemPropertyHelper,
82         Logging loggingService) {
83         this.httpsAuthClientFactory = httpsAuthClientFactory;
84         this.servletRequestHelper = servletRequestHelper;
85         this.systemPropertyHelper = systemPropertyHelper;
86         this.loggingService = loggingService;
87         initRestClient();
88     }
89
90     /**
91      * For testing purpose
92      */
93     AAIRestInterface(Optional<Client> client,
94         HttpsAuthClient httpsAuthClientFactory,
95         ServletRequestHelper servletRequestHelper,
96         SystemPropertyHelper systemPropertyHelper,
97         Logging loggingService){
98         this.httpsAuthClientFactory = httpsAuthClientFactory;
99         this.servletRequestHelper = servletRequestHelper;
100         this.systemPropertyHelper = systemPropertyHelper;
101         this.loggingService = loggingService;
102         if (client != null && client.isPresent()){
103             this.client = client.get();
104         }
105
106     }
107
108     /**
109      * Encode URL.
110      *
111      * @param nodeKey the node key
112      * @return the string
113      * @throws UnsupportedEncodingException the unsupported encoding exception
114      */
115     public String encodeURL (String nodeKey) throws UnsupportedEncodingException {
116         return URLEncoder.encode(nodeKey, "UTF-8").replaceAll("\\+", "%20");
117     }
118
119     protected void initRestClient() {
120         initRestClient(false);
121     }
122
123
124     private void initRestClient(boolean propagateExceptions) {
125         if (client == null) {
126             try {
127                 client = httpsAuthClientFactory.getClient(HttpClientMode.WITH_KEYSTORE);
128                 VidMetricLogClientFilter metricLogClientFilter = new VidMetricLogClientFilter();
129                 client.register(metricLogClientFilter);
130             } catch (Exception e) {
131                 logger.info(EELFLoggerDelegate.errorLogger, "Exception in REST call to DB in initRestClient" + e.toString());
132                 logger.debug(EELFLoggerDelegate.debugLogger, "Exception in REST call to DB : " + e.toString());
133                 if (propagateExceptions) {
134                     ExceptionUtils.rethrow(e);
135                 }
136             }
137         }
138     }
139
140
141
142     /**
143      * Sets the rest srvr base URL.
144      *
145      * @param baseURL the base URL
146      */
147     public void setRestSrvrBaseURL(String baseURL)
148     {
149         if (baseURL == null) {
150             logger.info(EELFLoggerDelegate.errorLogger, "REST Server base URL cannot be null.");
151             logger.debug(EELFLoggerDelegate.debugLogger, "REST Server base URL cannot be null.");
152         }
153
154         restSrvrBaseURL = baseURL;
155     }
156
157     /**
158      * Gets the rest srvr base URL.
159      *
160      * @return the rest srvr base URL
161      */
162     public String getRestSrvrBaseURL() {
163         return restSrvrBaseURL;
164     }
165
166
167     public ResponseWithRequestInfo RestGet(String fromAppId, String transId, URI requestUri, boolean xml) {
168         return RestGet(fromAppId, transId, requestUri, xml, false);
169     }
170
171     public ResponseWithRequestInfo RestGet(String fromAppId, String transId, URI requestUri, boolean xml, boolean propagateExceptions) {
172         return doRest(fromAppId, transId, requestUri, null, HttpMethod.GET, xml, propagateExceptions);
173     }
174
175     public ResponseWithRequestInfo doRest(String fromAppId, String transId, URI requestUri, String payload, HttpMethod method, boolean xml, boolean propagateExceptions) {
176         return doRest(fromAppId, transId, ()->systemPropertyHelper.getFullServicePath(requestUri), payload, method, xml, propagateExceptions);
177     }
178
179
180     public ResponseWithRequestInfo doRest(String fromAppId, String transId, Supplier<String> urlSupplier, String payload, HttpMethod method, boolean xml, boolean propagateExceptions) {
181         String url = null;
182         String methodName = "Rest"+method.name();
183         try {
184
185             url = urlSupplier.get();
186
187             initRestClient(propagateExceptions);
188
189             logger.debug(EELFLoggerDelegate.debugLogger, methodName + START_STRING);
190             logger.debug(EELFLoggerDelegate.debugLogger, url + " for the get REST API");
191
192             loggingService.logRequest(outgoingRequestsLogger, method, url, payload);
193
194             final Response response;
195
196             Invocation.Builder requestBuilder = client.target(url)
197                 .request()
198                 .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON)
199                 .header(FROM_APP_ID_HEADER, fromAppId)
200                 .header("Content-Type", MediaType.APPLICATION_JSON)
201                 ;
202
203             requestBuilder = systemPropertyHelper.isClientCertEnabled() ?
204                 requestBuilder : authenticateRequest(requestBuilder);
205
206             Invocation restInvocation = StringUtils.isEmpty(payload) ?
207                 requestBuilder.build(method.name()) :
208                 requestBuilder.build(method.name(), Entity.entity(payload, MediaType.APPLICATION_JSON));
209
210             response = restInvocation.invoke();
211             loggingService.logResponse(outgoingRequestsLogger, method, url, response);
212
213             if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
214                 logger.debug(EELFLoggerDelegate.debugLogger, methodName + SUCCESSFUL_API_MESSAGE);
215                 logger.info(EELFLoggerDelegate.errorLogger, methodName + SUCCESSFUL_API_MESSAGE);
216             } else {
217                 logger.debug(EELFLoggerDelegate.debugLogger, getInvalidResponseLogMessage(url, methodName, response));
218             }
219             return new ResponseWithRequestInfo(response, url, method);
220         } catch (Exception e) {
221             logger.debug(EELFLoggerDelegate.debugLogger, getFailedResponseLogMessage(url, methodName, e));
222             if (propagateExceptions) {
223                 throw new ExceptionWithRequestInfo(method, defaultIfNull(url, ""), e);
224             } else {
225                 return new ResponseWithRequestInfo(null, url, method);
226             }
227         }
228     }
229
230     protected String extractOrGenerateRequestId() {
231         return servletRequestHelper.extractOrGenerateRequestId();
232     }
233
234
235     public ResponseWithRequestInfo RestPut(String fromAppId, String path, String payload, boolean xml, boolean propagateExceptions) {
236         return doRest(fromAppId, UUID.randomUUID().toString(), Unchecked.toURI(path), payload, HttpMethod.PUT, xml, propagateExceptions);
237     }
238
239
240     public Response RestPost(String fromAppId, String path, String payload, boolean xml) {
241         ResponseWithRequestInfo response = doRest(
242             fromAppId,
243             UUID.randomUUID().toString(),
244             ()->systemPropertyHelper.getServiceBasePath(path),
245             payload,
246             HttpMethod.POST,
247             xml,
248             false);
249         return response.getResponse();
250     }
251
252     protected String getFailedResponseLogMessage(String path, String methodName, Exception e) {
253         return methodName + URL_DECLARATION + path + ", Exception: " + e.toString();
254     }
255
256     protected String getValidResponseLogMessage(String methodName) {
257         return methodName + URL_DECLARATION;
258     }
259
260     protected String getInvalidResponseLogMessage(String path, String methodName, Response cres) {
261         return methodName + " with status=" + cres.getStatus() + URL_DECLARATION + path;
262     }
263
264     private Invocation.Builder authenticateRequest(Invocation.Builder requestBuilder) throws InvalidPropertyException, UnsupportedEncodingException {
265         return requestBuilder
266             .header("Authorization", "Basic " + systemPropertyHelper.getEncodedCredentials());
267     }
268
269 }