2 * ================================================================================
3 * DCAE DMaaP Bus Controller REST Client
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ================================================================================
20 package org.openecomp.dcae.dmaapbc.client;
22 import java.io.IOException;
25 import org.apache.http.Consts;
26 import org.apache.http.HttpEntity;
27 import org.apache.http.HttpHost;
28 import org.apache.http.auth.AuthScope;
29 import org.apache.http.auth.UsernamePasswordCredentials;
30 import org.apache.http.client.AuthCache;
31 import org.apache.http.client.ClientProtocolException;
32 import org.apache.http.client.CredentialsProvider;
33 import org.apache.http.client.config.RequestConfig;
34 import org.apache.http.client.config.RequestConfig.Builder;
35 import org.apache.http.client.methods.CloseableHttpResponse;
36 import org.apache.http.client.methods.HttpDelete;
37 import org.apache.http.client.methods.HttpGet;
38 import org.apache.http.client.methods.HttpPost;
39 import org.apache.http.client.methods.HttpPut;
40 import org.apache.http.client.methods.HttpRequestBase;
41 import org.apache.http.client.protocol.HttpClientContext;
42 import org.apache.http.client.utils.URIBuilder;
43 import org.apache.http.entity.ContentType;
44 import org.apache.http.entity.StringEntity;
45 import org.apache.http.impl.auth.BasicScheme;
46 import org.apache.http.impl.client.BasicAuthCache;
47 import org.apache.http.impl.client.BasicCredentialsProvider;
48 import org.apache.http.impl.client.CloseableHttpClient;
49 import org.apache.http.impl.client.HttpClients;
50 import org.apache.http.util.EntityUtils;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
55 * Provides a basic client to access a REST endpoint, optionally using HTTP
56 * basic authentication.
58 * Caveat: If HTTPS access is used and the server uses a self-signed
59 * certificate, the local trust store must be extended appropriately. The client
60 * throws exceptions if the JVM cannot validate the server certificate.
62 public class SimpleRestClientBase {
64 private static Logger logger = LoggerFactory.getLogger(SimpleRestClientBase.class);
67 * Credentials for HTTP basic authentication (optional).
69 private final String username;
70 private final String password;
75 private Integer connectTimeoutMs = null;
76 private Integer connectionRequestTimeoutMs = null;
77 private Integer socketTimeoutMs = null;
80 * Constructs a client that does not use any authentication and uses Apache
81 * HTTPD client default values for timeouts.
83 public SimpleRestClientBase() {
84 this(null, null, null, null, null);
88 * Convenience constructor to build a client that uses the specified
89 * username and password for basic HTTP authentication on all requests. In
90 * other words, this client pre-emptively sends the "Basic" header instead
91 * of first trying the request without, failing, negotiating, then sending
95 * User name for basic HTTP authentication.
97 * Password for basic HTTP authentication.
99 public SimpleRestClientBase(final String username, final String password) {
100 this(username, password, null, null, null);
104 * Convenience constructor to build a client that uses the specified
105 * timeouts on all requests.
107 * @param connectTimeoutMs
108 * Connection timeout, in milliseconds
109 * @param connectionRequestTimeoutMs
110 * Connection request timeout, in milliseconds
111 * @param socketTimeoutMs
112 * Socket timeout, in milliseconds
114 public SimpleRestClientBase(final Integer connectTimeoutMs, final Integer connectionRequestTimeoutMs,
115 final Integer socketTimeoutMs) {
116 this(null, null, connectTimeoutMs, connectionRequestTimeoutMs, socketTimeoutMs);
120 * Constructs a client with the specified credentials and timeout values.
123 * User name for basic HTTP authentication; ignored if null
125 * Password for basic HTTP authentication; ignored if null
126 * @param connectTimeoutMs
128 * @param connectionRequestTimeoutMs
130 * @param socketTimeoutMs
133 public SimpleRestClientBase(final String username, final String password, final Integer connectTimeoutMs,
134 final Integer connectionRequestTimeoutMs, final Integer socketTimeoutMs) {
135 this.username = username;
136 this.password = password;
137 this.connectTimeoutMs = null;
138 this.connectionRequestTimeoutMs = null;
139 this.socketTimeoutMs = null;
143 * Constructs and sends a GET request for the URI.
147 * @return Result of the get
151 public HttpStatusAndResponse<String> getRestContent(final URI uri) throws Exception {
152 HttpGet httpGet = new HttpGet(uri);
153 return doRestRequest(httpGet);
157 * Constructs and sends a POST request using the specified body.
163 * @return Result of the post; null if an error happens
167 public HttpStatusAndResponse<String> postRestContent(final URI uri, final String json) throws Exception {
168 HttpPost httpPost = new HttpPost(uri);
169 StringEntity postEntity = new StringEntity(json, ContentType.create("application/json", Consts.UTF_8));
170 httpPost.setEntity(postEntity);
171 return doRestRequest(httpPost);
175 * Constructs and sends a PUT request using the specified body.
181 * @return Result of the put; null if an error happens
185 public HttpStatusAndResponse<String> putRestContent(final URI uri, final String json) throws Exception {
186 HttpPut httpPut = new HttpPut(uri);
187 StringEntity postEntity = new StringEntity(json, ContentType.create("application/json", Consts.UTF_8));
188 httpPut.setEntity(postEntity);
189 return doRestRequest(httpPut);
193 * Constructs and sends a DELETE request for the URI.
197 * @return Result of the get
201 public HttpStatusAndResponse<String> deleteRestContent(final URI uri) throws Exception {
202 HttpDelete httpDel = new HttpDelete(uri);
203 return doRestRequest(httpDel);
207 * Executes the specified request and gathers the response.
210 * HttpGet, HttpPost, etc.
211 * @return Status code and response body
212 * @throws ClientProtocolException
213 * On HTTP protocol error
214 * @throws IOException
215 * On read/write error
217 private HttpStatusAndResponse<String> doRestRequest(final HttpRequestBase request)
218 throws ClientProtocolException, IOException {
220 // Set up authentication if needed
221 final HttpClientContext context = HttpClientContext.create();
222 if (this.username != null || this.password != null) {
223 UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(this.username, this.password);
224 CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
225 credentialsProvider.setCredentials(AuthScope.ANY, credentials);
226 context.setCredentialsProvider(credentialsProvider);
228 HttpHost host = new HttpHost(request.getURI().getHost(), request.getURI().getPort(),
229 request.getURI().getScheme());
230 AuthCache authCache = new BasicAuthCache();
231 authCache.put(host, new BasicScheme());
232 context.setAuthCache(authCache);
234 final Builder requestConfigBuilder = RequestConfig.custom();
235 if (connectionRequestTimeoutMs != null)
236 requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeoutMs);
237 if (connectTimeoutMs != null)
238 requestConfigBuilder.setConnectTimeout(connectTimeoutMs);
239 if (socketTimeoutMs != null)
240 requestConfigBuilder.setSocketTimeout(socketTimeoutMs);
241 RequestConfig requestConfig = requestConfigBuilder.build();
242 final CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
243 CloseableHttpResponse response = null;
244 String responseJson = null;
246 response = httpClient.execute(request, context);
247 // Some methods return non-200 on success
248 logger.debug("doRestRequest: status is {}", response.getStatusLine());
249 HttpEntity entity = response.getEntity();
250 // This is common; don't warn
251 if (entity == null) {
252 logger.debug("doRestRequest: Entity is null");
254 // entity content length is never set;
255 // this naively tries to read everything.
256 responseJson = EntityUtils.toString(entity);
257 EntityUtils.consume(entity);
258 // Don't give back empty string;
259 // it has no more meaning than null.
260 if (responseJson.length() == 0)
264 if (response != null)
267 if (response == null)
269 return new HttpStatusAndResponse<String>(response.getStatusLine().getStatusCode(), responseJson);
273 * Basic test invocation.
276 * Expect 1 argument, the URL of a REST endpoint.
278 * if anything goes wrong
280 public static void main(String[] args) throws Exception {
281 if (args.length != 1)
282 throw new IllegalArgumentException("Expect 1 argument: REST URL for GET");
283 SimpleRestClientBase client = new SimpleRestClientBase();
284 URIBuilder uriBuilder = new URIBuilder(args[0]);
285 URI uri = uriBuilder.build();
286 HttpStatusAndResponse<String> hsr = client.getRestContent(uri);
287 System.out.println("Response code is " + hsr.getStatusCode());
288 System.out.println(hsr.getResponseString());
289 System.out.println("main ends.");