View Javadoc

1   package com.atlassian.sal.core.net;
2   
3   import org.apache.commons.httpclient.HttpClient;
4   import org.apache.commons.httpclient.UsernamePasswordCredentials;
5   import org.apache.commons.httpclient.auth.AuthScope;
6   import org.apache.commons.lang.StringUtils;
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import java.net.URI;
11  import java.net.URISyntaxException;
12  
13  /**
14   * Configures the proxy on the HttpClient instance, reads the proxy configuration
15   * from the following system properties:
16   *
17   *<ul>
18   *     <li><b>http.proxyHost</b></li>
19   *     <li><b>http.proxyPort</b> (optional, default to 80)</li>
20   *</ul>
21   * A list of excluded hosts can be provided to bypass the proxy:
22   *<ul>
23   *     <li><b>http.nonProxyHosts</b> (format: www.atlassian.com|*.example.com) - The only wildcard supported is the simple suffix match.</li>
24   *</ul>
25   * If the proxy needs authentication, the credentials must be provided using:
26   *<ul>
27   *     <li><b>http.proxyUser</b></li>
28   *     <li><b>http.proxyPassword</b></li>
29   *</ul>
30   */
31  public class HttpClientProxyConfig {
32  
33      private static final Logger log = LoggerFactory.getLogger(HttpClientProxyConfig.class);
34  
35      /**
36       * @param client The client to configure the proxy of
37       * @param remoteUrl The remote URL
38       */
39      protected void configureProxy(final HttpClient client, final String remoteUrl)
40      {
41          if (client == null)
42          {
43              throw new IllegalArgumentException("Please provide a valid HttpClient instance");
44          }
45          final String proxyHost = System.getProperty("http.proxyHost");
46  
47          URI uri;
48          try
49          {
50              uri = new URI(remoteUrl);
51          } catch (final URISyntaxException e)
52          {
53              log.warn("Invalid url: " + remoteUrl, e);
54              return;
55          }
56          if (proxyHost != null && !isNonProxyHost(uri.getHost()))
57          {
58              int port = 80;
59              try
60              {
61                  port = Integer.parseInt(System.getProperty("http.proxyPort", "80"));
62              }
63              catch (final NumberFormatException e)
64              {
65                  log.warn("System property 'http.proxyPort' is not a number. Defaulting to 80.");
66              }
67  
68              client.getHostConfiguration().setProxy(proxyHost, port);
69              if(proxyAuthenticationRequired())
70              {
71                  client.getState().setProxyCredentials(new AuthScope(proxyHost,port),
72                          new UsernamePasswordCredentials(System.getProperty("http.proxyUser"),
73                                  System.getProperty("http.proxyPassword")));
74              }
75          }
76      }
77  
78      /**
79       * Discover whether or not proxy authentication is required; if we are behind a proxy then it is required,
80       * otherwise it isn't
81       *
82       * @return true if proxy authentication is required, false otherwise
83       */
84      private boolean proxyAuthenticationRequired()
85      {
86          return System.getProperty("http.proxyUser") != null;
87      }
88  
89      private boolean isNonProxyHost(final String host)
90      {
91          if (StringUtils.isBlank(host))
92          {
93              return true;
94          }
95          final String httpNonProxyHosts = System.getProperty("http.nonProxyHosts");
96          if (StringUtils.isBlank(httpNonProxyHosts))
97          {
98              // checking if property was misspelt, notice there is no 's' at the end of this property
99              if (StringUtils.isBlank(System.getProperty("http.nonProxyHost")))
100             {
101                 log.warn("The system property http.nonProxyHost is set. You probably meant to set http.nonProxyHosts.");
102             }
103             return false;
104         }
105         final String[] nonProxyHosts = httpNonProxyHosts.split("\\|");
106         for (final String nonProxyHost : nonProxyHosts) {
107             if (nonProxyHost.startsWith("*")) {
108                 if (host.endsWith(nonProxyHost.substring(1))) {
109                     return true;
110                 }
111             } else if (host.equals(nonProxyHost)) {
112                 return true;
113             }
114         }
115         return false;
116     }
117 
118 }