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
29 /**
30 * The configuration of the forward proxy to use with {@link org.eclipse.jetty.client.HttpClient}.
31 * <p />
32 * Applications add subclasses of {@link Proxy} to this configuration via:
33 * <pre>
34 * ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
35 * proxyConfig.getProxies().add(new HttpProxy(proxyHost, 8080));
36 * </pre>
37 *
38 * @see HttpClient#getProxyConfiguration()
39 */
40 public class ProxyConfiguration
41 {
42 private final List<Proxy> proxies = new ArrayList<>();
43
44 public List<Proxy> getProxies()
45 {
46 return proxies;
47 }
48
49 public Proxy match(Origin origin)
50 {
51 for (Proxy proxy : getProxies())
52 {
53 if (proxy.matches(origin))
54 return proxy;
55 }
56 return null;
57 }
58
59 public static abstract class Proxy
60 {
61 private final Set<String> included = new HashSet<>();
62 private final Set<String> excluded = new HashSet<>();
63 private final Origin.Address address;
64 private final boolean secure;
65
66 protected Proxy(Origin.Address address, boolean secure)
67 {
68 this.address = address;
69 this.secure = secure;
70 }
71
72 /**
73 * @return the address of this proxy
74 */
75 public Origin.Address getAddress()
76 {
77 return address;
78 }
79
80 /**
81 * @return whether the connection to the proxy must be secured via TLS
82 */
83 public boolean isSecure()
84 {
85 return secure;
86 }
87
88 /**
89 * @return the list of origins that must be proxied
90 * @see #matches(Origin)
91 * @see #getExcludedAddresses()
92 */
93 public Set<String> getIncludedAddresses()
94 {
95 return included;
96 }
97
98 /**
99 * @return the list of origins that must not be proxied.
100 * @see #matches(Origin)
101 * @see #getIncludedAddresses()
102 */
103 public Set<String> getExcludedAddresses()
104 {
105 return excluded;
106 }
107
108 /**
109 * @return an URI representing this proxy, or null if no URI can represent this proxy
110 */
111 public URI getURI()
112 {
113 return null;
114 }
115
116 /**
117 * Matches the given {@code origin} with the included and excluded addresses,
118 * returning true if the given {@code origin} is to be proxied.
119 *
120 * @param origin the origin to test for proxying
121 * @return true if the origin must be proxied, false otherwise
122 */
123 public boolean matches(Origin origin)
124 {
125 boolean result = included.isEmpty();
126 Origin.Address address = origin.getAddress();
127 for (String included : this.included)
128 {
129 if (matches(address, included))
130 {
131 result = true;
132 break;
133 }
134 }
135 for (String excluded : this.excluded)
136 {
137 if (matches(address, excluded))
138 {
139 result = false;
140 break;
141 }
142 }
143 return result;
144 }
145
146 private boolean matches(Origin.Address address, String pattern)
147 {
148 // TODO: add support for CIDR notation like 192.168.0.0/24, see DoSFilter
149 int colon = pattern.indexOf(':');
150 if (colon < 0)
151 return pattern.equals(address.getHost());
152 String host = pattern.substring(0, colon);
153 String port = pattern.substring(colon + 1);
154 return host.equals(address.getHost()) && port.equals(String.valueOf(address.getPort()));
155 }
156
157 /**
158 * @param connectionFactory the nested {@link ClientConnectionFactory}
159 * @return a new {@link ClientConnectionFactory} for this {@link Proxy}
160 */
161 public abstract ClientConnectionFactory newClientConnectionFactory(ClientConnectionFactory connectionFactory);
162
163 @Override
164 public String toString()
165 {
166 return address.toString();
167 }
168 }
169
170 }