View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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 }