All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tascape.reactor.ws.comm.WebServiceCommunication Maven / Gradle / Ivy

/*
 * Copyright 2015 - 2016 Nebula Bay.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.tascape.reactor.ws.comm;

import com.tascape.reactor.SystemConfiguration;
import com.tascape.reactor.comm.EntityCommunication;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Linsong Wang
 */
public class WebServiceCommunication extends EntityCommunication {
    private static final Logger LOG = LoggerFactory.getLogger(WebServiceCommunication.class);

    /**
     * Web service host name or IP address
     */
    public static final String SYSPROP_HOST = "reactor.comm.ws.HOST";

    /**
     * Web service port number
     */
    public static final String SYSPROP_PORT = "reactor.comm.ws.PORT";

    /**
     * Certificate used to authenticate web service client
     */
    public static final String SYSPROP_CLIENT_CERT = "reactor.comm.ws.CLIENT_CERT";

    /**
     * Passcode of client certificate
     */
    public static final String SYSPROP_CLIENT_CERT_PASS = "reactor.comm.ws.CLIENT_CERT_PASS";

    /**
     * Web service user name for basic authentication
     */
    public static final String SYSPROP_USER = "reactor.comm.ws.USER";

    /**
     * Web service user password for basic authentication
     */
    public static final String SYSPROP_PASS = "reactor.comm.ws.PASS";

    /**
     * Socket timeout in millisecond, default to 0
     */
    public static final String SYSPROP_SO_TIMEOUT = "reactor.comm.ws.SO_TIMEOUT";

    /**
     * Web service user agent string
     */
    public static final String USER_AGENT
        = "Mozilla/5.0 (Reactor; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) "
        + "Chrome/18.0.1025.151 Safari/535.19";

    public enum HTTP_METHOD {
        GET, GET_JSONObject, GET_JSONArray, POST, POST_JSONObject, PUT, PUT_JSONObject, DELETE, DELETE_JSONObject, HEAD,
    }

    private static String cookieSpec = CookieSpecs.DEFAULT;

    private final HttpHost httpHost;

    private final String baseUri;

    private String clientCertificate;

    private String keyPassword;

    private String username;

    private String password;

    private CredentialsProvider userPassCredentialsProvider;

    private AuthCache authCache;

    private final CookieStore cookieStore = new BasicCookieStore();

    private CloseableHttpClient client;

    private IdleConnectionMonitorThread cmt;

    private final Map headers = new HashMap<>();

    private final Map responseTime = new HashMap<>();

    public static void setCookieSpec(String aCookieSpec) {
        cookieSpec = aCookieSpec;
    }

    /**
     * Gets the response body as string of specified uri.
     *
     * @param uri http/https uri
     *
     * @return response body
     *
     * @throws IOException in case of any IO related issue
     */
    public static String getUri(String uri) throws IOException {
        CloseableHttpClient c = newHttpClient(new URL(uri));
        HttpGet get = new HttpGet(uri);
        LOG.debug("GET {}", uri);
        CloseableHttpResponse res = c.execute(get, HttpClientContext.create());
        return checkResponse(res);
    }

    /**
     * Gets the response headers of specified uri.
     *
     * @param uri http/https uri
     *
     * @return response headers
     *
     * @throws IOException in case of any IO related issue
     */
    public static Header[] headUri(String uri) throws IOException {
        CloseableHttpClient c = newHttpClient(new URL(uri));
        HttpHead head = new HttpHead(uri);
        LOG.debug("HEAD {}", uri);
        CloseableHttpResponse res = c.execute(head, HttpClientContext.create());
        checkResponse(res);
        return res.getAllHeaders();
    }

    /**
     * Gets the response header value of specified uri.
     *
     * @param uri  http/https uri
     * @param name header name
     *
     * @return response header value
     *
     * @throws IOException in case of any IO related issue
     */
    public static String headUri(String uri, String name) throws IOException {
        return Stream.of(headUri(uri)).filter(h -> h.getName().equals(name)).findFirst().get().getValue();
    }

    /**
     * Needs system properties.
     * 
    *
  • reactor.comm.ws.HOST, default to localhost if not set
  • *
  • reactor.comm.ws.PORT, default to 443 if not set
  • *
  • reactor.comm.ws.USER, no default
  • *
  • reactor.comm.ws.PASS, no default
  • *
  • reactor.comm.ws.CLIENT_CERT, no default
  • *
  • reactor.comm.ws.CLIENT_CERT_PASS, no default
  • *
* * @return an instance of communication * * @throws Exception if having problem connecting to the service */ public static WebServiceCommunication newInstance() throws Exception { return newInstance(""); } /** * Needs system properties. *
    *
  • reactor.comm.ws.HOST$name, fall back to reactor.comm.ws.HOST, and then default to localhost if not set
  • *
  • reactor.comm.ws.PORT$name, fall back to reactor.comm.ws.PORT, then default to 443 if not set
  • *
  • reactor.comm.ws.USER$name, fall back to reactor.comm.ws.USER, no default
  • *
  • reactor.comm.ws.PASS$name, fall back to reactor.comm.ws.PASS, no default
  • *
  • reactor.comm.ws.CLIENT_CERT$name, fall back to reactor.comm.ws.CLIENT_CERT, no default
  • *
  • reactor.comm.ws.CLIENT_CERT_PASS$name, fall back to reactor.comm.ws.CLIENT_CERT_PASS, no default
  • *
* * @param name name of each require system property, such as ".SERVER_ONE" * * @return an instance of communication * * @throws Exception if having problem connecting to the service */ public static WebServiceCommunication newInstance(String name) throws Exception { SystemConfiguration sysConfig = SystemConfiguration.getInstance(); String host = sysConfig.getProperty(WebServiceCommunication.SYSPROP_HOST + name); if (host == null) { host = sysConfig.getProperty(WebServiceCommunication.SYSPROP_HOST, "localhost"); } int port = sysConfig.getIntProperty(WebServiceCommunication.SYSPROP_PORT + name); if (port == Integer.MIN_VALUE) { port = sysConfig.getIntProperty(WebServiceCommunication.SYSPROP_PORT, 443); } WebServiceCommunication wsc = new WebServiceCommunication(host, port); String user = sysConfig.getProperty(WebServiceCommunication.SYSPROP_USER + name); if (user == null) { user = sysConfig.getProperty(WebServiceCommunication.SYSPROP_USER); } String pass = sysConfig.getProperty(WebServiceCommunication.SYSPROP_PASS + name); if (pass == null) { pass = sysConfig.getProperty(WebServiceCommunication.SYSPROP_PASS); } if (null != user && null != pass) { wsc.setBasicUsernamePassword(user, pass); } String clientCert = sysConfig.getProperty(WebServiceCommunication.SYSPROP_CLIENT_CERT + name); if (clientCert == null) { clientCert = sysConfig.getProperty(WebServiceCommunication.SYSPROP_CLIENT_CERT); } String clientCertPass = sysConfig.getProperty(WebServiceCommunication.SYSPROP_CLIENT_CERT_PASS + name); if (clientCertPass == null) { clientCertPass = sysConfig.getProperty(WebServiceCommunication.SYSPROP_CLIENT_CERT_PASS); } if (null != clientCert && null != clientCertPass) { wsc.setClientCertificate(clientCert, clientCertPass); } wsc.connect(); return wsc; } /** * Constructor. * * @param httpHost HTTP host info */ public WebServiceCommunication(HttpHost httpHost) { this(httpHost.getHostName(), httpHost.getPort()); } /** * Constructor. * * @param host host DNS name or IP * @param port https for *443, http for others */ public WebServiceCommunication(String host, int port) { if (port % 1000 == 443) { this.baseUri = "https://" + host + (port == 443 ? "" : ":" + port); this.httpHost = new HttpHost(host, port, "https"); } else { this.baseUri = "http://" + host + (port == 80 ? "" : ":" + port); this.httpHost = new HttpHost(host, port, "http"); } } /** * Calls this to provide client certificate. * * @param clientCertificate client certificate file * @param keyPassword client certificate password */ public void setClientCertificate(String clientCertificate, String keyPassword) { LOG.debug("use client certificate/password {}/********", clientCertificate); this.clientCertificate = clientCertificate; this.keyPassword = keyPassword; } /** * Calls this to provide username and password. This will use Basic authentication, with a header such as * "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" * * @param username user name * @param password password */ public void setBasicUsernamePassword(String username, String password) { this.username = username; this.password = password; LOG.debug("use basic username/password {}/********", username); userPassCredentialsProvider = new BasicCredentialsProvider(); userPassCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(httpHost, basicAuth); } /** * Adds HTTP header for all subsequent HTTP requests. * * @param name HTTP header name * @param value HTTP header value */ public void setHeader(String name, String value) { this.headers.put(name, value); } public Map getHeaders() { return headers; } /** * Removes HTTP header for all subsequent HTTP requests. * * @param name HTTP header name * * @return the previous header value associated with name, or null if there was no mapping for * name. */ public String removeHeader(String name) { return this.headers.remove(name); } /** * * @throws Exception in case of any issue */ @Override public void connect() throws Exception { this.disconnect(); SSLContextBuilder contextBuilder = SSLContexts.custom(); contextBuilder.loadTrustMaterial(null, acceptingTrustStrategy); RegistryBuilder registryBuilder = RegistryBuilder.create() .register("http", new PlainConnectionSocketFactory()); HttpClientBuilder httpClientBuilder = HttpClients.custom() .setUserAgent(USER_AGENT) .setKeepAliveStrategy(keepAliveStrategy) .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(cookieSpec).build()) .setDefaultCookieStore(this.cookieStore) .setRedirectStrategy(new LaxRedirectStrategy()); if (userPassCredentialsProvider != null) { httpClientBuilder.addInterceptorFirst(preemptiveAuth); } if (clientCertificate != null && keyPassword != null) { LOG.debug("client cert {}", clientCertificate); try (FileInputStream instream = new FileInputStream(new File(clientCertificate))) { KeyStore ks = KeyStore.getInstance("pkcs12"); ks.load(instream, keyPassword.toCharArray()); contextBuilder.loadKeyMaterial(ks, keyPassword.toCharArray()); } } if ("https".equals(httpHost.getSchemeName())) { SSLContext sslContext = contextBuilder.build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); registryBuilder.register("https", sslsf); httpClientBuilder.setSSLSocketFactory(sslsf); } Registry socketFactoryRegistry = registryBuilder.build(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry); cm.setMaxTotal(200); cm.setDefaultMaxPerRoute(20); cm.setValidateAfterInactivity(5000); cm.setMaxPerRoute(new HttpRoute(httpHost), 200); cm.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(sysConfig.getIntProperty(SYSPROP_SO_TIMEOUT, 0)) .build()); cmt = new IdleConnectionMonitorThread(cm); cmt.setDaemon(true); cmt.start(); this.client = httpClientBuilder.setConnectionManager(cm).build(); } /** * @throws Exception in case of any issue */ @Override public void disconnect() throws Exception { try { if (cmt != null) { cmt.shutdown(); } } finally { if (this.client != null) { this.client.close(); } } } /** * Issues HTTP HEAD request, returns response headers. * * @param endpoint endpoint of request url * * @return response headers * * @throws IOException in case of any IO related issue */ public Header[] head(String endpoint) throws IOException { return this.head(endpoint, ""); } /** * Issues HTTP HEAD request, returns response headers. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response headers * * @throws IOException in case of any IO related issue */ public Header[] head(String endpoint, String params) throws IOException { return this.head(endpoint, params, ""); } /** * Issues HTTP HEAD request, returns response headers. * * @param endpoint endpoint of request url * @param params request line parameters * @param requestId request id for record response time in millisecond * * @return response headers * * @throws IOException in case of any IO related issue */ public Header[] head(String endpoint, String params, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("HEAD {}", url); HttpHead head = new HttpHead(url); this.addHeaders(head); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(head, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } check(response); return response.getAllHeaders(); } /** * Issues HTTP GET request, converts response body to a JSON object. * * @param endpoint endpoint of request url * * @return response body to a JSON object * * @throws IOException in case of any IO related issue */ public JSONObject getJsonObject(String endpoint) throws IOException { String res = this.get(endpoint, null, null); try { return new JSONObject(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, converts response body to a JSON object. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body to a JSON object * * @throws IOException in case of any IO related issue */ public JSONObject getJsonObject(String endpoint, String params) throws IOException { String res = this.get(endpoint, params, null); try { return new JSONObject(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, converts response body to a JSON object. * * @param endpoint endpoint of request url * @param params request line parameters * @param requestId request id for record response time in millisecond * * @return response body to a JSON object * * @throws IOException in case of any IO related issue */ public JSONObject getJsonObject(String endpoint, String params, String requestId) throws IOException { String res = this.get(endpoint, params, requestId); try { return new JSONObject(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, converts response body to a JSON array object. * * @param endpoint endpoint of request url * * @return response body to a JSON array object * * @throws IOException in case of any IO related issue */ public JSONArray getJsonArray(String endpoint) throws IOException { String res = this.get(endpoint, null, null); try { return new JSONArray(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, converts response body to a JSON array object. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body to a JSON array object * * @throws IOException in case of any IO related issue */ public JSONArray getJsonArray(String endpoint, String params) throws IOException { String res = this.get(endpoint, params, null); try { return new JSONArray(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, converts response body to a JSON array object. * * @param endpoint endpoint of request url * @param params request line parameters * @param requestId request id for record response time in millisecond * * @return response body to a JSON array object * * @throws IOException in case of any IO related issue */ public JSONArray getJsonArray(String endpoint, String params, String requestId) throws IOException { String res = this.get(endpoint, params, requestId); try { return new JSONArray(res); } catch (JSONException ex) { LOG.warn(res); throw ex; } } /** * Issues HTTP GET request, returns response body as string. * * @param endpoint endpoint of request url * * @return response body * * @throws IOException in case of any IO related issue */ public String get(String endpoint) throws IOException { return this.get(endpoint, null); } /** * Issues HTTP GET request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body * * @throws IOException in case of any IO related issue */ public String get(String endpoint, String params) throws IOException { return this.get(endpoint, params, null); } /** * Issues HTTP GET request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String get(String endpoint, String params, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} GET {}", this.hashCode(), url); HttpGet get = new HttpGet(url); this.addHeaders(get); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(get, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Issues HTTP DELETE request, returns response body as string. * * @param endpoint endpoint of request url * * @return response body * * @throws IOException in case of any IO related issue */ public String delete(String endpoint) throws IOException { return this.delete(endpoint, ""); } /** * Issues HTTP DELETE request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body * * @throws IOException in case of any IO related issue */ public String delete(String endpoint, String params) throws IOException { return this.delete(endpoint, params, ""); } /** * Issues HTTP DELETE request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String delete(String endpoint, String params, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} DELETE {}", this.hashCode(), url); HttpDelete delete = new HttpDelete(url); this.addHeaders(delete); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(delete, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Issues HTTP DELETE request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param body request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String delete(String endpoint, String params, String body, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} DELETE {}", this.hashCode(), url); HttpPost delete = new HttpPost(url) { @Override public String getMethod() { return HttpDelete.METHOD_NAME; } }; StringEntity entity = new StringEntity(body); entity.setContentType(ContentType.TEXT_PLAIN.getMimeType()); delete.setEntity(entity); this.addHeaders(delete); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(delete, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Issues HTTP DELETE request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param json request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String deleteJson(String endpoint, String params, JSONObject json, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} DELETE {}", this.hashCode(), url); HttpPost delete = new HttpPost(url) { @Override public String getMethod() { return HttpDelete.METHOD_NAME; } }; StringEntity entity = new StringEntity(json.toString()); entity.setContentType(ContentType.APPLICATION_JSON.getMimeType()); delete.setEntity(entity); this.addHeaders(delete); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(delete, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param json request body * * @return response body * * @throws IOException in case of any IO related issue */ public String postJson(String endpoint, JSONObject json) throws IOException { return this.postJson(endpoint, "", json); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param json request body * * @return response body * * @throws IOException in case of any IO related issue */ public String postJson(String endpoint, String params, JSONObject json) throws IOException { return this.postJson(endpoint, params, json, ""); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param json request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String postJson(String endpoint, String params, JSONObject json, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} POST {}", this.hashCode(), url); HttpPost post = new HttpPost(url); StringEntity entity = new StringEntity(json.toString()); entity.setContentType(ContentType.APPLICATION_JSON.getMimeType()); post.setEntity(entity); this.addHeaders(post); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(post, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } String res = check(response); return res; } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * * @return response body * * @throws IOException in case of any IO related issue */ public String post(String endpoint) throws IOException { return this.post(endpoint, ""); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body * * @throws IOException in case of any IO related issue */ public String post(String endpoint, String params) throws IOException { return this.post(endpoint, params, ""); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param body request body * * @return response body * * @throws IOException in case of any IO related issue */ public String post(String endpoint, String params, String body) throws IOException { return this.post(endpoint, params, body, ""); } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param body request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String post(String endpoint, String params, String body, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} POST {}", this.hashCode(), url); HttpPost post = new HttpPost(url); StringEntity entity = new StringEntity(body); entity.setContentType(ContentType.TEXT_PLAIN.getMimeType()); post.setEntity(entity); this.addHeaders(post); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(post, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } String res = check(response); return res; } /** * Issues HTTP POST request, returns response body as string. * * @param endpoint endpoint of request url * @param entity request entity * * @return response body * * @throws IOException in case of any IO related issue */ public String postEntity(String endpoint, HttpEntity entity) throws IOException { return this.postEntity(endpoint, "", entity, ""); } /** * Issues HTTP POST request, returns response body as string. * http://www.baeldung.com/httpclient-multipart-upload *
     * {@code
     * HttpPost post = new HttpPost("http://echo.200please.com");
     * InputStream inputStream = new FileInputStream(zipFileName);
     * File file = new File(imageFileName);
     * String message = "This is a multipart post";
     * MultipartEntityBuilder builder = MultipartEntityBuilder.create();
     * builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
     * builder.addBinaryBody("upfile", file, ContentType.DEFAULT_BINARY, imageFileName);
     * builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), zipFileName);
     * builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
     *
     * HttpEntity entity = builder.build();
     * post.setEntity(entity);
     * HttpResponse response = client.execute(post);
     * }
     * 
* * @param endpoint endpoint of request url * @param params request line parameters * @param entity request entity * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String postEntity(String endpoint, String params, HttpEntity entity, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} POST {}", this.hashCode(), url); HttpPost post = new HttpPost(url); post.setEntity(entity); this.addHeaders(post); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(post, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } String res = check(response); return res; } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param json request body * * @return response body * * @throws IOException in case of any IO related issue */ public String putJson(String endpoint, JSONObject json) throws IOException { return this.putJson(endpoint, "", json); } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param json request body * * @return response body * * @throws IOException in case of any IO related issue */ public String putJson(String endpoint, String params, JSONObject json) throws IOException { return this.putJson(endpoint, params, json, ""); } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param json request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String putJson(String endpoint, String params, JSONObject json, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} PUT {}", this.hashCode(), url); HttpPut put = new HttpPut(url); StringEntity entity = new StringEntity(json.toString()); entity.setContentType(ContentType.APPLICATION_JSON.getMimeType()); put.setEntity(entity); this.addHeaders(put); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(put, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * * @return response body * * @throws IOException in case of any IO related issue */ public String put(String endpoint, String params) throws IOException { return this.put(endpoint, params, ""); } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param body request body * * @return response body * * @throws IOException in case of any IO related issue */ public String put(String endpoint, String params, String body) throws IOException { return this.put(endpoint, params, body, ""); } /** * Issues HTTP PUT request, returns response body as string. * * @param endpoint endpoint of request url * @param params request line parameters * @param body request body * @param requestId request id for record response time in millisecond * * @return response body * * @throws IOException in case of any IO related issue */ public String put(String endpoint, String params, String body, String requestId) throws IOException { String url = String.format("%s%s%s", this.baseUri, endpoint, StringUtils.isBlank(params) ? "" : "?" + params); LOG.debug("{} PUT {}", this.hashCode(), url); HttpPut put = new HttpPut(url); StringEntity entity = new StringEntity(body); entity.setContentType(ContentType.TEXT_PLAIN.getMimeType()); put.setEntity(entity); this.addHeaders(put); HttpClientContext context = this.getHttpClientContext(); long start = System.currentTimeMillis(); CloseableHttpResponse response = this.client.execute(put, context); if (!StringUtils.isBlank(requestId)) { this.responseTime.put(requestId, System.currentTimeMillis() - start); } return check(response); } /** * Gets response time previously recorded. * * @param reqId request id * * @return time in millisecond */ public Long getResponseTime(String reqId) { return responseTime.get(reqId); } /** * Clears response time previously recorded. * * @param reqId request id */ public void clearResponseTime(String reqId) { this.responseTime.remove(reqId); } /** * Encodes with UTF-8. * * @param param string to encode * * @return UTF-8 encoded string * * @throws UnsupportedEncodingException if UTF-8 is not supported */ public static String encode(String param) throws UnsupportedEncodingException { return URLEncoder.encode(param, "UTF-8"); } /** * Encodes with UTF-8. * * @param param string to decode * * @return UTF-8 decoded string * * @throws UnsupportedEncodingException if UTF-8 is not supported */ public static String decode(String param) throws UnsupportedEncodingException { return URLDecoder.decode(param, "UTF-8"); } /** * Gets the host name and port. * * @return HTTPHost */ public HttpHost getHttpHost() { return httpHost; } public String getClientCertificate() { return clientCertificate; } public String getKeyPassword() { return keyPassword; } public String getUsername() { return username; } public String getPassword() { return password; } public CloseableHttpClient getClient() { return client; } private void addHeaders(HttpRequest request) { this.headers.entrySet().forEach(header -> { request.setHeader(header.getKey(), header.getValue()); }); } private HttpClientContext getHttpClientContext() { HttpClientContext context = HttpClientContext.create(); if (this.userPassCredentialsProvider != null) { context.setCredentialsProvider(userPassCredentialsProvider); context.setAuthCache(authCache); BasicScheme basicAuth = new BasicScheme(); context.setAttribute("preemptive-auth", basicAuth); } this.cookieStore.getCookies().forEach(c -> { LOG.trace("outgoing {} {} {}", c.getName() + "=" + c.getValue(), c.getDomain(), c.getPath()); }); return context; } private String check(CloseableHttpResponse response) throws IOException { this.cookieStore.getCookies().forEach(c -> { LOG.trace("incoming {} {} {}", c.getName() + "=" + c.getValue(), c.getDomain(), c.getPath()); }); String res = ""; if (response.getEntity() != null) { res = EntityUtils.toString(response.getEntity()); } int code = response.getStatusLine().getStatusCode(); if (code < 200 || code >= 300) { LOG.warn("{}", response.getStatusLine()); throw new WebServiceException(code, res); } return res; } private final TrustStrategy acceptingTrustStrategy = (X509Certificate[] certificate, String authType) -> true; private final ConnectionKeepAliveStrategy keepAliveStrategy = (HttpResponse response, HttpContext context) -> { HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { HeaderElement he = it.nextElement(); String param = he.getName(); String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { return Long.parseLong(value) * 1000; } catch (NumberFormatException ignore) { LOG.trace(ignore.getMessage()); } } } return 30000; }; private final HttpRequestInterceptor preemptiveAuth = (final HttpRequest request, final HttpContext context) -> { AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE); if (authState.getAuthScheme() == null) { AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth"); CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute( HttpClientContext.CREDS_PROVIDER); HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST); if (authScheme != null) { Credentials creds = credsProvider.getCredentials( new AuthScope(targetHost.getHostName(), targetHost.getPort())); if (creds == null) { throw new HttpException("No credentials for preemptive authentication"); } authState.update(authScheme, creds); } } }; private static String checkResponse(CloseableHttpResponse response) throws IOException { String res = ""; if (response.getEntity() != null) { res = EntityUtils.toString(response.getEntity()); } int code = response.getStatusLine().getStatusCode(); if (code < 200 || code >= 300) { LOG.warn("{}", response.getStatusLine()); throw new WebServiceException(code, res); } return res; } private static CloseableHttpClient newHttpClient(URL url) throws IOException { HttpClientBuilder httpClientBuilder = HttpClients.custom() .setUserAgent(USER_AGENT) .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).build()) .setRedirectStrategy(new LaxRedirectStrategy()); RegistryBuilder registryBuilder = RegistryBuilder.create() .register("http", new PlainConnectionSocketFactory()); if ("https".equals(url.getProtocol())) { SSLContextBuilder contextBuilder = SSLContexts.custom(); TrustStrategy ats = (X509Certificate[] certificate, String authType) -> true; try { contextBuilder.loadTrustMaterial(null, ats); SSLContext sslContext = contextBuilder.build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); registryBuilder.register("https", sslsf); httpClientBuilder.setSSLSocketFactory(sslsf); } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException ex) { throw new IOException(ex); } } Registry socketFactoryRegistry = registryBuilder.build(); HttpClientConnectionManager cm = new BasicHttpClientConnectionManager(socketFactoryRegistry); return httpClientBuilder.setConnectionManager(cm).build(); } private static class IdleConnectionMonitorThread extends Thread { private final HttpClientConnectionManager connMgr; private volatile boolean shutdown; public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) { super(); this.connMgr = connMgr; } @Override public void run() { try { while (!shutdown) { synchronized (this) { wait(5000); connMgr.closeExpiredConnections(); connMgr.closeIdleConnections(10, TimeUnit.SECONDS); } } } catch (InterruptedException ex) { LOG.warn("interrupted", ex); } } public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } } } public static void main(String[] args) throws Exception { WebServiceCommunication ws = new WebServiceCommunication("127.0.0.0", 18088); ws.connect(); Header[] headers = ws.head("thr/dashboard.xhtml"); Stream.of(headers).forEach(h -> { LOG.debug("{} = {}", h.getName(), h.getValue()); }); headers = WebServiceCommunication.headUri("https://127.0.0.1:18088/thr/dashboard.xhtml"); Stream.of(headers).forEach(h -> { LOG.debug("{} = {}", h.getName(), h.getValue()); }); ws = new WebServiceCommunication("bit.ly", 80); ws.connect(); String status = ws.get("1c1mBAI"); LOG.info(status); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy