1 //
2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.client;
20
21 import java.net.URI;
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26
27 import org.eclipse.jetty.io.ClientConnectionFactory;
28 import org.eclipse.jetty.util.HostPort;
29
30 /**
31 * The configuration of the forward proxy to use with {@link org.eclipse.jetty.client.HttpClient}.
32 * <p>
33 * Applications add subclasses of {@link Proxy} to this configuration via:
34 * <pre>
35 * ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
36 * proxyConfig.getProxies().add(new HttpProxy(proxyHost, 8080));
37 * </pre>
38 *
39 * @see HttpClient#getProxyConfiguration()
40 */
41 public class ProxyConfiguration
42 {
43 private final List<Proxy> proxies = new ArrayList<>();
44
45 public List<Proxy> getProxies()
46 {
47 return proxies;
48 }
49
50 public Proxy match(Origin origin)
51 {
52 for (Proxy proxy : getProxies())
53 {
54 if (proxy.matches(origin))
55 return proxy;
56 }
57 return null;
58 }
59
60 public static abstract class Proxy
61 {
62 // TO use IPAddress Map
63 private final Set<String> included = new HashSet<>();
64 private final Set<String> excluded = new HashSet<>();
65 private final Origin.Address address;
66 private final boolean secure;
67
68 protected Proxy(Origin.Address address, boolean secure)
69 {
70 this.address = address;
71 this.secure = secure;
72 }
73
74 /**
75 * @return the address of this proxy
76 */
77 public Origin.Address getAddress()
78 {
79 return address;
80 }
81
82 /**
83 * @return whether the connection to the proxy must be secured via TLS
84 */
85 public boolean isSecure()
86 {
87 return secure;
88 }
89
90 /**
91 * @return the list of origins that must be proxied
92 * @see #matches(Origin)
93 * @see #getExcludedAddresses()
94 */
95 public Set<String> getIncludedAddresses()
96 {
97 return included;
98 }
99
100 /**
101 * @return the list of origins that must not be proxied.
102 * @see #matches(Origin)
103 * @see #getIncludedAddresses()
104 */
105 public Set<String> getExcludedAddresses()
106 {
107 return excluded;
108 }
109
110 /**
111 * @return an URI representing this proxy, or null if no URI can represent this proxy
112 */
113 public URI getURI()
114 {
115 return null;
116 }
117
118 /**
119 * Matches the given {@code origin} with the included and excluded addresses,
120 * returning true if the given {@code origin} is to be proxied.
121 *
122 * @param origin the origin to test for proxying
123 * @return true if the origin must be proxied, false otherwise
124 */
125 public boolean matches(Origin origin)
126 {
127 if (getAddress().equals(origin.getAddress()))
128 return false;
129
130 boolean result = included.isEmpty();
131 Origin.Address address = origin.getAddress();
132 for (String included : this.included)
133 {
134 if (matches(address, included))
135 {
136 result = true;
137 break;
138 }
139 }
140 for (String excluded : this.excluded)
141 {
142 if (matches(address, excluded))
143 {
144 result = false;
145 break;
146 }
147 }
148 return result;
149 }
150
151 private boolean matches(Origin.Address address, String pattern)
152 {
153 // TODO: add support for CIDR notation like 192.168.0.0/24, see DoSFilter
154 HostPort hostPort = new HostPort(pattern);
155 String host = hostPort.getHost();
156 int port = hostPort.getPort();
157 return host.equals(address.getHost()) && ( port<=0 || port==address.getPort() );
158 }
159
160 /**
161 * @param connectionFactory the nested {@link ClientConnectionFactory}
162 * @return a new {@link ClientConnectionFactory} for this {@link Proxy}
163 */
164 public abstract ClientConnectionFactory newClientConnectionFactory(ClientConnectionFactory connectionFactory);
165
166 @Override
167 public String toString()
168 {
169 return address.toString();
170 }
171 }
172
173 }