// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.client; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.util.HostPort; /** * The configuration of the forward proxy to use with {@link org.eclipse.jetty.client.HttpClient}. * <p> * Applications add subclasses of {@link Proxy} to this configuration via: * <pre> * ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); * proxyConfig.getProxies().add(new HttpProxy(proxyHost, 8080)); * </pre> * * @see HttpClient#getProxyConfiguration() */ public class ProxyConfiguration { private final List<Proxy> proxies = new ArrayList<>(); public List<Proxy> getProxies() { return proxies; } public Proxy match(Origin origin) { for (Proxy proxy : getProxies()) { if (proxy.matches(origin)) return proxy; } return null; } public static abstract class Proxy { // TO use IPAddress Map private final Set<String> included = new HashSet<>(); private final Set<String> excluded = new HashSet<>(); private final Origin.Address address; private final boolean secure; protected Proxy(Origin.Address address, boolean secure) { this.address = address; this.secure = secure; } /** * @return the address of this proxy */ public Origin.Address getAddress() { return address; } /** * @return whether the connection to the proxy must be secured via TLS */ public boolean isSecure() { return secure; } /** * @return the list of origins that must be proxied * @see #matches(Origin) * @see #getExcludedAddresses() */ public Set<String> getIncludedAddresses() { return included; } /** * @return the list of origins that must not be proxied. * @see #matches(Origin) * @see #getIncludedAddresses() */ public Set<String> getExcludedAddresses() { return excluded; } /** * @return an URI representing this proxy, or null if no URI can represent this proxy */ public URI getURI() { return null; } /** * Matches the given {@code origin} with the included and excluded addresses, * returning true if the given {@code origin} is to be proxied. * * @param origin the origin to test for proxying * @return true if the origin must be proxied, false otherwise */ public boolean matches(Origin origin) { if (getAddress().equals(origin.getAddress())) return false; boolean result = included.isEmpty(); Origin.Address address = origin.getAddress(); for (String included : this.included) { if (matches(address, included)) { result = true; break; } } for (String excluded : this.excluded) { if (matches(address, excluded)) { result = false; break; } } return result; } private boolean matches(Origin.Address address, String pattern) { // TODO: add support for CIDR notation like 192.168.0.0/24, see DoSFilter HostPort hostPort = new HostPort(pattern); String host = hostPort.getHost(); int port = hostPort.getPort(); return host.equals(address.getHost()) && ( port<=0 || port==address.getPort() ); } /** * @param connectionFactory the nested {@link ClientConnectionFactory} * @return a new {@link ClientConnectionFactory} for this {@link Proxy} */ public abstract ClientConnectionFactory newClientConnectionFactory(ClientConnectionFactory connectionFactory); @Override public String toString() { return address.toString(); } } }