View Javadoc

1   package com.atlassian.httpclient.apache.httpcomponents;
2   
3   import com.atlassian.httpclient.api.BannedHostException;
4   import com.atlassian.httpclient.api.HostResolver;
5   
6   import java.net.InetAddress;
7   import java.net.UnknownHostException;
8   import java.util.List;
9   import java.util.stream.Collectors;
10  
11  /**
12   * Banned host resolver can be used to restrict the IPs that a host may resolve to. When utilised in a http client
13   * each call will at some point will pass the endpoint to connect to through the {@link #resolve(String)} method.
14   * <p>
15   * This implementation will throw an exception if it receives a host that resolves to an IP in the restricted list.
16   * <p>
17   * Do note, that even if a specific IP is to be connected to, the IP will still be resolved through this class and
18   * eventually be blocked if required.
19   */
20  public class BannedHostResolver implements HostResolver {
21  
22      private final List<IpAddressMatcher> cidrs;
23  
24      /**
25       * @param bannedCidrs list of cidrs to block from resolving
26       */
27      public BannedHostResolver(List<String> bannedCidrs) {
28          cidrs = bannedCidrs.stream()
29                  .map(IpAddressMatcher::new)
30                  .collect(Collectors.toList());
31      }
32  
33      @Override
34      public InetAddress[] resolve(String host) throws UnknownHostException {
35          InetAddress[] addresses = DefaultHostResolver.INSTANCE.resolve(host);
36          if (isBanned(addresses)) {
37              throw new BannedHostException("The host " + host + " has been blocked for access");
38          }
39          return addresses;
40      }
41  
42      private boolean isBanned(InetAddress[] addresses) {
43          for (IpAddressMatcher cidr : cidrs) {
44              for (InetAddress address : addresses) {
45                  String hostAddress = address.getHostAddress();
46                  if (cidr.matches(hostAddress)) {
47                      return true;
48                  }
49              }
50          }
51          return false;
52      }
53  }