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