2 * Copyright (C) 2018 Bell Canada.
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.
16 package org.onap.ccsdk.sli.adaptors.netbox.impl;
18 import static org.apache.http.HttpHeaders.ACCEPT;
19 import static org.apache.http.HttpHeaders.AUTHORIZATION;
20 import static org.apache.http.HttpHeaders.CONTENT_TYPE;
22 import java.io.IOException;
23 import java.nio.charset.Charset;
24 import java.security.KeyManagementException;
25 import java.security.KeyStoreException;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.Scanner;
28 import java.util.concurrent.CompletableFuture;
29 import java.util.concurrent.CompletionStage;
30 import java.util.function.Function;
31 import javax.net.ssl.SSLContext;
32 import org.apache.http.HttpEntityEnclosingRequest;
33 import org.apache.http.HttpResponse;
34 import org.apache.http.client.methods.HttpDelete;
35 import org.apache.http.client.methods.HttpPost;
36 import org.apache.http.client.methods.HttpUriRequest;
37 import org.apache.http.concurrent.FutureCallback;
38 import org.apache.http.conn.ssl.NoopHostnameVerifier;
39 import org.apache.http.entity.StringEntity;
40 import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
41 import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
42 import org.apache.http.ssl.SSLContexts;
43 import org.apache.http.ssl.TrustStrategy;
44 import org.onap.ccsdk.sli.adaptors.netbox.api.IpamException;
45 import org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties;
47 public class NetboxHttpClient implements AutoCloseable {
49 private static final String APPLICATION_JSON = "application/json";
51 private final CloseableHttpAsyncClient client;
52 private final String url;
53 private final String token;
55 // Used by the blueprint container
56 public NetboxHttpClient(NetboxProperties properties) {
57 this(properties.getHost(), properties.getApiKey());
60 NetboxHttpClient(final String url, final String token) {
64 final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
65 final SSLContext sslContext;
67 sslContext = SSLContexts.custom()
68 .loadTrustMaterial(null, acceptingTrustStrategy).build();
69 } catch (final NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
70 throw new IllegalStateException("Can't create http client", e);
72 client = HttpAsyncClientBuilder.create()
73 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
74 .setSSLContext(sslContext)
79 // Has to be public for blueprint container to access it
85 public void close() throws IOException {
89 CompletionStage<HttpResponse> post(final String uri, final String requestBody) {
90 return sendRequest(uri, requestBody, HttpPost::new);
93 CompletionStage<HttpResponse> delete(final String uri) {
94 return sendRequest(uri, HttpDelete::new);
97 static String getBodyAsString(final HttpResponse response) {
99 if (response.getEntity() != null) {
100 try (final Scanner s = new java.util.Scanner(response.getEntity().getContent()).useDelimiter("\\A")) {
101 body = s.hasNext() ? s.next() : "";
102 } catch (final IOException e) {
103 throw new IllegalStateException(e);
108 return response.toString() + "\n" + body;
111 private <T extends HttpUriRequest> CompletionStage<HttpResponse> sendRequest(final String uri,
112 final Function<String, T> supplier) {
113 final T request = supplier.apply(url + uri);
114 request.addHeader(ACCEPT, APPLICATION_JSON);
115 request.addHeader(CONTENT_TYPE, APPLICATION_JSON);
116 request.addHeader(AUTHORIZATION, "Token " + token);
117 return sendRequest(request);
120 private <T extends HttpEntityEnclosingRequest & HttpUriRequest>
121 CompletionStage<HttpResponse> sendRequest(final String uri, final String body,
122 final Function<String, T> supplier) {
123 final T request = supplier.apply(url + uri);
124 request.addHeader(ACCEPT, APPLICATION_JSON);
125 request.addHeader(CONTENT_TYPE, APPLICATION_JSON);
126 request.addHeader(AUTHORIZATION, "Token " + token);
127 request.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
128 return sendRequest(request);
131 private CompletionStage<HttpResponse> sendRequest(final HttpUriRequest request) {
132 final CompletableFuture<HttpResponse> future = new CompletableFuture<>();
133 client.execute(request, new FutureCallback<HttpResponse>() {
135 public void completed(final HttpResponse httpResponse) {
136 future.complete(httpResponse);
140 public void failed(final Exception e) {
141 future.completeExceptionally(new IpamException("Netbox request failed", e));
145 public void cancelled() {
146 future.cancel(false);