package org.netmelody.cieye.server.observation.protocol; import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScheme; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; 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.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.util.EntityUtils; import org.netmelody.cieye.core.logging.LogKeeper; import org.netmelody.cieye.core.logging.Logbook; public final class RestRequester implements GrapeVine { private static final Logbook LOG = LogKeeper.logbookFor(RestRequester.class); private final boolean privileged; private final CloseableHttpClient client; private final HttpClientContext context; public RestRequester(String username, String password) { privileged = !username.isEmpty(); final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); connManager.setMaxTotal(200); connManager.setDefaultMaxPerRoute(20); RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).build(); CredentialsProvider credsProvider = new BasicCredentialsProvider(); if (privileged) { credsProvider.setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(username, password)); } client = HttpClients.custom().setConnectionManager(connManager) .setDefaultRequestConfig(requestConfig) .setDefaultCredentialsProvider(credsProvider) .build(); context = HttpClientContext.create(); context.setAuthCache(new SingleAuthCache(new BasicScheme())); } @Override public boolean privileged() { return privileged; } @Override public String doGet(String url) { LOG.info(url); try { final HttpGet httpget = new HttpGet(url); httpget.setHeader("Accept", "application/json"); final ResponseHandler<String> responseHandler = new BasicResponseHandler(); return client.execute(httpget, responseHandler, context); } catch (HttpResponseException e) { if (e.getStatusCode() == 404) { LOG.info(url + " - 404 Not Found", e); return ""; } LOG.error(url, e); } catch (Exception e) { LOG.error(url, e); } return ""; } @Override public void doPost(String url) { LOG.info(url); try { client.execute(new HttpPost(url), new ConsumingResponseHandler(), context); } catch (Exception e) { LOG.error(url, e); } } @Override public void doPut(String url, String content) { LOG.info(url); try { final HttpPut put = new HttpPut(url); put.setEntity(new StringEntity(content)); client.execute(put, new ConsumingResponseHandler(), context); } catch (Exception e) { LOG.error(url, e); } } @Override public void shutdown() { try { client.close(); } catch (Exception e) { LOG.error("error shutting down", e); } } public static final class SingleAuthCache implements AuthCache { private AuthScheme authScheme; public SingleAuthCache(AuthScheme authScheme) { this.authScheme = authScheme; } @Override public void put(HttpHost host, AuthScheme authScheme) { this.authScheme = authScheme; } @Override public AuthScheme get(HttpHost host) { return this.authScheme; } @Override public void remove(HttpHost host) { return; } @Override public void clear() { return; } } public static final class ConsumingResponseHandler implements ResponseHandler<String> { @Override public String handleResponse(HttpResponse response) { final HttpEntity entity = response.getEntity(); final int statusCode = response.getStatusLine().getStatusCode(); try { if (statusCode >= 300 && statusCode != 302) { LOG.error("Failed to PUT/POST\n" + EntityUtils.toString(entity)); } EntityUtils.consume(entity); } catch (IOException e) { LOG.error("Failed to consume response entity"); } return ""; } } }