package com.philemonworks.critter.httpclient; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.impl.conn.DefaultRoutePlanner; import org.apache.http.protocol.HttpContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.philemonworks.critter.Launcher; import java.net.URI; import java.net.URISyntaxException; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import static com.philemonworks.critter.Constants.*; /** * <p> * This {@link org.apache.http.conn.routing.HttpRoutePlanner HttpRoutePlanner} implementation determines whether a proxy must be used for the current request * based on the given properties. * </p> * <p> * The {@link DefaultRoutePlanner} creates the corresponding {@link org.apache.http.conn.routing.HttpRoute}, so this class can return <code>NULL</code> when no * proxy is needed. * </p> */ @Singleton public class ProxyRoutePlanner extends DefaultRoutePlanner { private static final Logger LOGGER = LoggerFactory.getLogger(ProxyRoutePlanner.class); private final String httpProxy; private final String httpsProxy; private final String noProxy; @Inject public ProxyRoutePlanner( @Named(FORWARD_HTTP_PROXY) String httpProxy, @Named(FORWARD_HTTPS_PROXY) String httpsProxy, @Named(FORWARD_NO_PROXY) String noProxy) { super(null); this.httpProxy = httpProxy; this.httpsProxy = httpsProxy; this.noProxy = noProxy; } @Override protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException { HttpHost proxyHost = null; if (hostMustBeProxied(target)) { proxyHost = determineEnvironmentProxy(target.getSchemeName()); } return proxyHost; } private boolean hostMustBeProxied(HttpHost target) { if (StringUtils.isNotEmpty(noProxy)) { for (String noProxyHost : StringUtils.split(noProxy, ",")) { if (target.getHostName().endsWith(noProxyHost)) { LOGGER.debug("not proxying {}", target); return false; } } } return true; } private HttpHost determineEnvironmentProxy(String schemeName) { if (StringUtils.isNotEmpty(getProxyForSchemeName(schemeName))) { return createEnvironmentProxy(schemeName); } return null; } private String getProxyForSchemeName(String schemeName) { if (StringUtils.equalsIgnoreCase(schemeName, "http")) { return httpProxy; } if (StringUtils.equalsIgnoreCase(schemeName, "https")) { return httpsProxy; } throw new IllegalArgumentException("No proxy for schemeName [" + schemeName + "]"); } private HttpHost createEnvironmentProxy(String schemeName) { try { URI proxyUri = new URI(getProxyForSchemeName(schemeName)); LOGGER.debug("creating proxy host {}", proxyUri); return new HttpHost(proxyUri.getHost(), proxyUri.getPort(), proxyUri.getScheme()); } catch (URISyntaxException e) { LOGGER.warn("invalid proxy uri format: {}", e); return null; } } }