package com.signalfx.connection; import java.io.IOException; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.entity.ContentType; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.signalfx.endpoint.SignalFxReceiverEndpoint; import com.signalfx.metrics.SignalFxMetricsException; public abstract class AbstractHttpReceiverConnection { protected static final Logger log = LoggerFactory.getLogger(AbstractHttpReceiverConnection.class); // Do not modify this line. It is auto replaced to a version number. public static final String VERSION_NUMBER = "0.0.35-SNAPSHOT"; public static final String USER_AGENT = "SignalFx-java-client/" + VERSION_NUMBER; protected static final ObjectMapper MAPPER = new ObjectMapper(); protected static final ContentType JSON_TYPE = ContentType.APPLICATION_JSON; protected final CloseableHttpClient client; protected final HttpHost host; protected final RequestConfig requestConfig; protected AbstractHttpReceiverConnection( SignalFxReceiverEndpoint endpoint, int timeoutMs, HttpClientConnectionManager httpClientConnectionManager) { this.client = HttpClientBuilder.create() .setConnectionManager(httpClientConnectionManager) .build(); this.host = new HttpHost(endpoint.getHostname(), endpoint.getPort(), endpoint.getScheme()); final HttpHost proxy = createHttpProxyFromSystemProperties(endpoint.getHostname()); this.requestConfig = RequestConfig.custom().setSocketTimeout(timeoutMs) .setConnectionRequestTimeout(timeoutMs).setConnectTimeout(timeoutMs).setProxy(proxy).build(); } protected CloseableHttpResponse postToEndpoint(String auth, HttpEntity httpEntity, String endpoint) throws IOException { HttpPost http_post = new HttpPost(String.format("%s%s", host.toURI(), endpoint)); http_post.setConfig(requestConfig); http_post.setHeader("X-SF-TOKEN", auth); http_post.setHeader("User-Agent", USER_AGENT); http_post.setEntity(httpEntity); try { log.trace("Talking to endpoint {}", http_post); return client.execute(http_post); } catch (IOException e) { log.trace("Exception trying to execute {}, Exception: {} ", http_post, e); throw e; } } protected void checkHttpResponse(CloseableHttpResponse resp) throws SignalFxMetricsException { final String body; try { body = IOUtils.toString(resp.getEntity().getContent()); } catch (IOException e) { throw new SignalFxMetricsException("Unable to get reponse content", e); } if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { throw new SignalFxMetricsException("Invalid status code " + resp.getStatusLine().getStatusCode() + ": " + body); } if (!"\"OK\"".equals(body)) { throw new SignalFxMetricsException("Invalid response body: " + body); } } /** * method to create a httphost object based on java network proxy system properties * * http.proxyHost: the host name of the proxy server * http.proxyPort: the port number, the default value being 80 * http.nonProxyHosts: a list of hosts that should be reached directly, bypassing the proxy. * This is a list of patterns separated by '|'. * The patterns may start or end with a '*' for wildcards. * Any host matching one of these patterns will be reached through a * direct connection instead of through a proxy. * * @param endpointHostname the signalfx endpoint hostname * * @return an instance of HttpHost based on the java system properties * unless the http proxy host is not configured * OR if the nonProxyHosts rules include this endpoint * then null will be returned instead **/ protected HttpHost createHttpProxyFromSystemProperties(String endpointHostname) { String proxyHost = System.getProperty("http.proxyHost"); if ((proxyHost != null) && (proxyHost.trim().length() > 0)) { String nonProxyHosts = System.getProperty("http.nonProxyHosts"); if (nonProxyHosts != null) { // set host strings as regular expressions based on // nonProxyHosts rules nonProxyHosts = nonProxyHosts.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*?"); // set groups and alternations nonProxyHosts = "(" + nonProxyHosts.replaceAll("\\|", ")|(") + ")"; final Pattern pattern = Pattern.compile(nonProxyHosts); if (pattern.matcher(endpointHostname).find()) { // http proxy is not configured for this endpoint return null; } } String proxyPort = System.getProperty("http.proxyPort"); if ((proxyPort == null) || (proxyPort.trim().length() == 0)) { // port 80 is the default in java networking/proxy documentation proxyPort = "80"; } // return http proxy host return new HttpHost(proxyHost.trim(), Integer.parseInt(proxyPort.trim()), "http"); } // http proxy is not configured return null; } }