a91548fca6e1fab78ff7465f359671b781a24c27
[policy/models.git] / models-interactions / model-impl / rest / src / main / java / org / onap / policy / rest / RestManager.java
1 /*
2  * ============LICENSE_START=======================================================
3  * rest
4  * ================================================================================
5  * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019-2020 Nordix Foundation.
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
22 package org.onap.policy.rest;
23
24 import java.nio.charset.StandardCharsets;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import javax.xml.bind.DatatypeConverter;
28 import org.apache.commons.lang3.tuple.Pair;
29 import org.apache.http.HttpHeaders;
30 import org.apache.http.HttpResponse;
31 import org.apache.http.client.methods.HttpDelete;
32 import org.apache.http.client.methods.HttpGet;
33 import org.apache.http.client.methods.HttpPatch;
34 import org.apache.http.client.methods.HttpPost;
35 import org.apache.http.client.methods.HttpPut;
36 import org.apache.http.client.methods.HttpRequestBase;
37 import org.apache.http.conn.ssl.NoopHostnameVerifier;
38 import org.apache.http.entity.StringEntity;
39 import org.apache.http.impl.client.CloseableHttpClient;
40 import org.apache.http.impl.client.HttpClientBuilder;
41 import org.apache.http.util.EntityUtils;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class RestManager {
46     private static final Logger logger = LoggerFactory.getLogger(RestManager.class);
47
48     // Constants for string literals
49     private static final String CONTENT_TYPE = "Content-Type";
50
51     /**
52      * Perform REST PUT.
53      *
54      * @param url the url
55      * @param username the user name
56      * @param password the password
57      * @param headers any headers
58      * @param contentType what the content type is
59      * @param body body to send
60      * @return the response status code and the body
61      */
62     public Pair<Integer, String> put(String url, String username, String password, Map<String, String> headers,
63             String contentType, String body) {
64         var put = new HttpPut(url);
65         addHeaders(put, username, password, headers);
66         put.addHeader(CONTENT_TYPE, contentType);
67         try {
68             var input = new StringEntity(body);
69             input.setContentType(contentType);
70             put.setEntity(input);
71         } catch (Exception e) {
72             logger.error("put threw: ", e);
73             return null;
74         }
75         return sendRequest(put);
76     }
77
78     /**
79      * Perform REST Post.
80      *
81      * @param url the url
82      * @param username the user name
83      * @param password the password
84      * @param headers any headers
85      * @param contentType what the content type is
86      * @param body body to send
87      * @return the response status code and the body
88      */
89     public Pair<Integer, String> post(String url, String username, String password, Map<String, String> headers,
90             String contentType, String body) {
91         var post = new HttpPost(url);
92         addHeaders(post, username, password, headers);
93         post.addHeader(CONTENT_TYPE, contentType);
94         try {
95             var input = new StringEntity(body);
96             input.setContentType(contentType);
97             post.setEntity(input);
98         } catch (Exception e) {
99             logger.error("post threw: ", e);
100             return null;
101         }
102         return sendRequest(post);
103     }
104
105     /**
106      * Do a REST get.
107      *
108      * @param url URL
109      * @param username user name
110      * @param password password
111      * @param headers any headers to add
112      * @return a Pair for the response status and the body
113      */
114     public Pair<Integer, String> get(String url, String username, String password, Map<String, String> headers) {
115         var get = new HttpGet(url);
116         addHeaders(get, username, password, headers);
117         return sendRequest(get);
118     }
119
120     /**
121      * Perform REST Delete. <br/>
122      * <i>Note: Many REST endpoints will return a 400 error for delete requests with a non-empty body</i>
123      *
124      * @param url the url
125      * @param username the user name
126      * @param password the password
127      * @param headers any headers
128      * @param contentType what the content type is
129      * @param body body (optional) to send
130      * @return the response status code and the body
131      */
132     public Pair<Integer, String> delete(String url, String username, String password, Map<String, String> headers,
133             String contentType, String body) {
134         var delete = new HttpDeleteWithBody(url);
135         addHeaders(delete, username, password, headers);
136         if (body != null && !body.isEmpty()) {
137             delete.addHeader(CONTENT_TYPE, contentType);
138             try {
139                 var input = new StringEntity(body);
140                 input.setContentType(contentType);
141                 delete.setEntity(input);
142             } catch (Exception e) {
143                 logger.error("delete threw: ", e);
144                 return null;
145             }
146         }
147         return sendRequest(delete);
148     }
149
150     /**
151      * Perform REST Delete.
152      *
153      * @param url the url
154      * @param username the user name
155      * @param password the password
156      * @param headers any headers
157      * @return the response status code and the body
158      */
159     public Pair<Integer, String> delete(String url, String username, String password, Map<String, String> headers) {
160         var delete = new HttpDelete(url);
161         addHeaders(delete, username, password, headers);
162         return sendRequest(delete);
163     }
164
165     /**
166      * Perform REST Patch.
167      *
168      * @param url the url
169      * @param username the user name
170      * @param password the password
171      * @param headers any headers
172      * @param body body to send
173      * @return the response status code and the body
174      */
175     public Pair<Integer, String> patch(String url, String username, String password, Map<String, String> headers,
176             String body) {
177         var contentType = "application/merge-patch+json";
178         var patch = new HttpPatch(url);
179         addHeaders(patch, username, password, headers);
180         patch.addHeader(CONTENT_TYPE, contentType);
181         try {
182             var input = new StringEntity(body);
183             input.setContentType(contentType);
184             patch.setEntity(input);
185         } catch (Exception e) {
186             logger.error("patch threw: ", e);
187             return null;
188         }
189         return sendRequest(patch);
190     }
191
192     /**
193      * Send REST request.
194      *
195      * @param request http request to send
196      * @return the response status code and the body
197      */
198     private Pair<Integer, String> sendRequest(HttpRequestBase request) {
199         if (logger.isDebugEnabled()) {
200             logger.debug("***** sendRequest to url {}:", request.getURI());
201         }
202
203         try (CloseableHttpClient client =
204                 HttpClientBuilder.create().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build()) {
205             HttpResponse response = client.execute(request);
206             if (response != null) {
207                 var returnBody = EntityUtils.toString(response.getEntity(), "UTF-8");
208                 logger.debug("HTTP Response Status Code: {}", response.getStatusLine().getStatusCode());
209                 logger.debug("HTTP Response Body:");
210                 logger.debug(returnBody);
211
212                 return Pair.of(response.getStatusLine().getStatusCode(), returnBody);
213             } else {
214                 logger.error("Response from {} is null", request.getURI());
215                 return null;
216             }
217         } catch (Exception e) {
218             logger.error("Request failed to {}", request.getURI(), e);
219             return null;
220         }
221     }
222
223     /**
224      * Add header to the request.
225      *
226      * @param request http request to send
227      * @param username the user name
228      * @param password the password
229      * @param headers any headers
230      */
231     private void addHeaders(HttpRequestBase request, String username, String password, Map<String, String> headers) {
232         String authHeader = makeAuthHeader(username, password);
233         if (headers != null) {
234             for (Entry<String, String> entry : headers.entrySet()) {
235                 request.addHeader(entry.getKey(), headers.get(entry.getKey()));
236             }
237         }
238         if (authHeader != null) {
239             request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
240         }
241     }
242
243     private String makeAuthHeader(String username, String password) {
244         if (username == null || username.isEmpty()) {
245             return null;
246         }
247
248         String auth = username + ":" + (password == null ? "" : password);
249         return "Basic " + DatatypeConverter.printBase64Binary(auth.getBytes(StandardCharsets.ISO_8859_1));
250     }
251 }