2 * Copyright 2017 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.cli.fw.http.connect;
20 import java.io.IOException;
21 import java.net.MalformedURLException;
24 import java.nio.charset.StandardCharsets;
25 import java.security.cert.X509Certificate;
26 import java.util.HashMap;
27 import java.util.List;
29 import java.util.Map.Entry;
31 import javax.net.ssl.SSLContext;
32 import javax.net.ssl.TrustManager;
33 import javax.net.ssl.X509TrustManager;
35 import org.apache.http.Header;
36 import org.apache.http.HttpEntity;
37 import org.apache.http.HttpResponse;
38 import org.apache.http.annotation.Contract;
39 import org.apache.http.annotation.ThreadingBehavior;
40 import org.apache.http.client.CookieStore;
41 import org.apache.http.client.config.RequestConfig;
42 import org.apache.http.client.methods.HttpDelete;
43 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
44 import org.apache.http.client.methods.HttpGet;
45 import org.apache.http.client.methods.HttpPatch;
46 import org.apache.http.client.methods.HttpPost;
47 import org.apache.http.client.methods.HttpPut;
48 import org.apache.http.client.methods.HttpRequestBase;
49 import org.apache.http.config.Registry;
50 import org.apache.http.config.RegistryBuilder;
51 import org.apache.http.conn.HttpClientConnectionManager;
52 import org.apache.http.conn.socket.ConnectionSocketFactory;
53 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
54 import org.apache.http.cookie.Cookie;
55 import org.apache.http.entity.ContentType;
56 import org.apache.http.entity.StringEntity;
57 import org.apache.http.entity.mime.MultipartEntityBuilder;
58 import org.apache.http.impl.client.BasicCookieStore;
59 import org.apache.http.impl.client.HttpClients;
60 import org.apache.http.impl.client.LaxRedirectStrategy;
61 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
62 import org.apache.http.impl.cookie.BasicClientCookie;
63 import org.apache.http.protocol.BasicHttpContext;
64 import org.apache.http.protocol.HttpContext;
65 import org.apache.http.util.EntityUtils;
66 import org.onap.cli.fw.http.conf.OnapCommandHttpConstants;
67 import org.onap.cli.fw.http.error.OnapCommandHttpFailure;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70 import org.apache.http.client.protocol.HttpClientContext;
71 import org.apache.http.conn.ssl.NoopHostnameVerifier;
72 import org.apache.http.impl.client.CloseableHttpClient;
73 import javax.net.ssl.HostnameVerifier;
75 * Helps to make http connection.<br>
77 public class OnapHttpConnection {
79 private static Logger log = LoggerFactory.getLogger(OnapHttpConnection.class);
81 private CloseableHttpClient httpClient = null;
83 Map<String, String> mapCommonHeaders = new HashMap<> ();
85 public static class TrustAllX509TrustManager implements X509TrustManager {
88 public X509Certificate[] getAcceptedIssuers() {
89 return new X509Certificate[0];
93 public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { //NOSONAR
94 // No need to implement.
98 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { //NOSONAR
99 // No need to implement.
103 private void initHttpClient(boolean isSecured) throws OnapCommandHttpFailure {
104 if (this.httpClient == null) {
107 SSLContext sslContext = SSLContext.getInstance(OnapCommandHttpConstants.SSLCONTEST_TLS);
108 sslContext.init(null, new TrustManager[] { new TrustAllX509TrustManager() },
109 new java.security.SecureRandom());
110 HostnameVerifier hostnameVerifier = new NoopHostnameVerifier();
111 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
112 .<ConnectionSocketFactory>create()
113 .register("https", new SSLConnectionSocketFactory(sslContext, hostnameVerifier)).build();
114 HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); // NOSONAR
116 this.httpClient = HttpClients.custom().setConnectionManager(connManager)
117 .setRedirectStrategy(new LaxRedirectStrategy()).build();
119 this.httpClient = HttpClients.createDefault(); // NOSONAR
121 } catch (Exception e) {
122 throw new OnapCommandHttpFailure(e);
127 private Map<String, String> getHttpHeaders(HttpResponse resp) {
128 Map<String, String> result = new HashMap<>();
130 Header[] hs = resp.getAllHeaders();
131 for (int i = 0; i < hs.length; i++) {
132 result.put(hs[i].getName(), hs[i].getValue());
138 private String getResponseBody(HttpResponse resp) throws OnapCommandHttpFailure {
139 if (resp.getEntity() == null) {
143 String body = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8);
144 EntityUtils.consume(resp.getEntity());
146 } catch (IOException e) {
147 throw new OnapCommandHttpFailure(e);
151 private StringEntity getStringEntity(HttpInput input) {
152 return new StringEntity(input.getBody(), StandardCharsets.UTF_8);
161 * @throws OnapCommandHttpFailure
164 public HttpResult post(final HttpInput input) throws OnapCommandHttpFailure {
165 input.setMethod("post");
166 return this.request(input);
175 * @throws OnapCommandHttpFailure
178 public HttpResult get(final HttpInput input) throws OnapCommandHttpFailure {
179 input.setMethod("get");
180 return this.request(input);
189 * @throws OnapCommandHttpFailure
192 public HttpResult put(final HttpInput input) throws OnapCommandHttpFailure {
193 input.setMethod("put");
194 return this.request(input);
203 * @throws OnapCommandHttpFailure
206 public HttpResult delete(final HttpInput input) throws OnapCommandHttpFailure {
207 input.setMethod("delete");
208 return this.request(input);
211 public void setCommonHeaders(Map<String, String> headers) {
212 this.mapCommonHeaders = headers;
215 private void addCommonHeaders(HttpInput input) {
216 if (!input.isBinaryData() && !input.getReqHeaders().containsKey("Content-Type")) {
217 input.getReqHeaders().put("Content-Type", OnapCommandHttpConstants.APPLICATION_JSON);
220 if (!input.getReqHeaders().containsKey("Accept")) {
221 input.getReqHeaders().put("Accept", OnapCommandHttpConstants.APPLICATION_JSON);
224 for (Entry<String, String> header : this.mapCommonHeaders.entrySet()) {
225 if (!input.getReqHeaders().containsKey(header.getKey()))
226 input.getReqHeaders().put(header.getKey(), header.getValue());
230 private void addCommonCookies(HttpInput input, CookieStore cookieStore) {
231 for (Entry<String, String> header : this.mapCommonHeaders.entrySet()) {
232 //take care of overriden headers in OCS YAML
233 String value = input.getReqHeaders().getOrDefault(header.getKey(),
235 Cookie cookie = new BasicClientCookie(header.getKey(), value);
236 cookieStore.addCookie(cookie);
240 private void updateResultFromCookies(HttpResult result, List<Cookie> cookies) {
241 for (Cookie cookie : cookies) {
242 result.getRespCookies().put(cookie.getName(), cookie.getValue());
246 private String getDomain(String url) {
248 return new URL(url).getHost();
249 } catch (MalformedURLException e) {
250 // url is always proper !!
255 private void updateInputFromCookies(HttpInput input, CookieStore cookieStore) {
256 addCommonCookies(input, cookieStore);
257 for (String cookieName : input.getReqCookies().keySet()) {
258 BasicClientCookie cookie = new BasicClientCookie(cookieName, input.getReqCookies().get(cookieName));
259 cookie.setDomain(this.getDomain(input.getUri()));
260 cookieStore.addCookie(cookie);
266 * Handles http method requests.
271 * @throws OnapCommandHttpFailure
274 public HttpResult request(HttpInput input) throws OnapCommandHttpFailure {
275 this.addCommonHeaders(input);
277 HttpRequestBase requestBase = null;
278 if ("post".equals(input.getMethod())) {
279 HttpPost httpPost = new HttpPost();
280 if (input.isBinaryData() || !(input.getMultiparts().isEmpty())) {
281 httpPost.setEntity(getMultipartEntity(input));
283 httpPost.setEntity(this.getStringEntity(input));
285 requestBase = httpPost;
286 } else if ("put".equals(input.getMethod())) {
287 HttpPut httpPut = new HttpPut();
288 httpPut.setEntity(this.getStringEntity(input));
289 requestBase = httpPut;
290 } else if ("patch".equals(input.getMethod())) {
291 HttpPatch httpPatch = new HttpPatch();
292 httpPatch.setEntity(this.getStringEntity(input));
293 requestBase = httpPatch;
294 } else if ("get".equals(input.getMethod())) {
295 requestBase = new HttpGet();
296 } else if ("delete".equals(input.getMethod())) {
297 if (!input.getBody().isEmpty()) {
298 HttpDeleteWithBody httpDelete = new HttpDeleteWithBody();
299 httpDelete.setEntity(new StringEntity(input.getBody(), ContentType.APPLICATION_JSON));
300 requestBase = httpDelete;
302 requestBase = new HttpDelete();
305 throw new IllegalArgumentException("Invalid HTTP method");
308 requestBase.setURI(URI.create(input.getUri()));
309 requestBase.setConfig(RequestConfig.custom()
310 .setSocketTimeout(600000).setConnectTimeout(600000).build());
312 for (Entry<String, String> h : input.getReqHeaders().entrySet()) {
313 requestBase.addHeader(h.getKey(), h.getValue());
316 HttpResult result = new HttpResult();
319 CookieStore cookieStore = new BasicCookieStore();
320 updateInputFromCookies(input, cookieStore);
321 HttpContext localContext = new BasicHttpContext();
322 localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
324 this.initHttpClient(input.getUri().startsWith("https"));
326 HttpResponse resp = this.httpClient.execute(requestBase, localContext);
327 String respContent = this.getResponseBody(resp);
328 result.setBody(respContent);
329 result.setStatus(resp.getStatusLine().getStatusCode());
330 result.setRespHeaders(this.getHttpHeaders(resp));
331 this.updateResultFromCookies(result, cookieStore.getCookies());
332 } catch (Exception e) { // NOSONAR
333 throw new OnapCommandHttpFailure(e);
339 public void close() throws IOException {
340 this.mapCommonHeaders.clear();
341 if (this.httpClient != null) {
342 this.httpClient.close();
346 private HttpEntity getMultipartEntity(HttpInput input) {
347 if (!input.getMultiparts().isEmpty()) {
348 MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
349 for (HttpInput.Part part: input.getMultiparts()) {
350 if (part.isBinary()) {
351 File file = new File(part.getContent());
352 entityBuilder.addBinaryBody(
355 ContentType.APPLICATION_OCTET_STREAM,
358 entityBuilder.addTextBody(part.getName(), part.getContent(), ContentType.APPLICATION_JSON);
362 return entityBuilder.build();
364 String fileTag = (!input.getMultipartEntityName().isEmpty()) ? input.getMultipartEntityName() : "file";
365 File file = new File(input.getBody().trim());
366 return MultipartEntityBuilder
368 .addBinaryBody(fileTag, file, ContentType.create("application/octet-stream"), file.getName())
373 @Contract(threading = ThreadingBehavior.UNSAFE)
374 static class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
376 public HttpDeleteWithBody() {
380 public String getMethod() {
381 return OnapCommandHttpConstants.DELETE.toUpperCase();