View Javadoc

1   package com.atlassian.sal.core.net;
2   
3   import com.atlassian.sal.api.net.NonMarshallingRequestFactory;
4   import com.atlassian.sal.api.net.Request.MethodType;
5   import org.apache.http.HttpHost;
6   import org.apache.http.auth.AuthScope;
7   import org.apache.http.auth.ChallengeState;
8   import org.apache.http.auth.Credentials;
9   import org.apache.http.auth.UsernamePasswordCredentials;
10  import org.apache.http.client.AuthCache;
11  import org.apache.http.client.CredentialsProvider;
12  import org.apache.http.client.protocol.HttpClientContext;
13  import org.apache.http.conn.HttpClientConnectionManager;
14  import org.apache.http.conn.routing.HttpRoutePlanner;
15  import org.apache.http.impl.auth.BasicScheme;
16  import org.apache.http.impl.client.BasicCredentialsProvider;
17  import org.apache.http.impl.client.CloseableHttpClient;
18  import org.apache.http.impl.client.HttpClients;
19  import org.apache.http.protocol.HttpRequestExecutor;
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  /**
24   * Does NOT support json/xml object marshalling. Use the atlassian-rest implementation of {@link
25   * com.atlassian.sal.api.net.RequestFactory} instead.
26   */
27  public class HttpClientRequestFactory implements NonMarshallingRequestFactory<HttpClientRequest>
28  {
29      private static final Logger log = LoggerFactory.getLogger(HttpClientRequestFactory.class);
30  
31      private final ProxyConfig proxyConfig;
32  
33      public HttpClientRequestFactory()
34      {
35          this(new SystemPropertiesProxyConfig());
36      }
37  
38      public HttpClientRequestFactory(final ProxyConfig proxyConfig)
39      {
40          this.proxyConfig = proxyConfig;
41      }
42  
43      /* (non-Javadoc)
44       * @see com.atlassian.sal.api.net.RequestFactory#createMethod(com.atlassian.sal.api.net.Request.MethodType, java.lang.String)
45       */
46      public HttpClientRequest createRequest(final MethodType methodType, final String url)
47      {
48          log.debug("Creating HttpClientRequest with proxy config:", proxyConfig);
49  
50          final CloseableHttpClient httpClient = createHttpClient();
51          final HttpClientContext clientContext = createClientContext();
52          return new HttpClientRequest(httpClient, clientContext, methodType, url);
53      }
54  
55      protected CloseableHttpClient createHttpClient()
56      {
57          return HttpClients.custom()
58                  .useSystemProperties()
59                  .setRoutePlanner(getRoutePlanner())
60                  .setRequestExecutor(getRequestExecutor())
61                  .setConnectionManager(getConnectionManager())
62                  .build();
63      }
64  
65      protected HttpClientContext createClientContext()
66      {
67          final HttpClientContext httpClientContext = HttpClientContext.create();
68          final AuthCache authCache = new AllPortsAuthCache();
69          final CredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
70  
71          if(proxyConfig.requiresAuthentication())
72          {
73              HttpHost proxyHost = new HttpHost(proxyConfig.getHost(), proxyConfig.getPort());
74              final AuthScope proxyAuthScope = new AuthScope(proxyHost);
75              final Credentials proxyCredentials = new UsernamePasswordCredentials(proxyConfig.getUser(),
76                      proxyConfig.getPassword());
77              basicCredentialsProvider.setCredentials(proxyAuthScope, proxyCredentials);
78  
79              // This ensures that proxy authentication is preemptive.
80              BasicScheme proxyScheme = new BasicScheme(ChallengeState.PROXY);
81              authCache.put(proxyHost, proxyScheme);
82          }
83  
84          httpClientContext.setCredentialsProvider(basicCredentialsProvider);
85          httpClientContext.setAuthCache(authCache);
86          return httpClientContext;
87      }
88  
89      public boolean supportsHeader()
90      {
91          return true;
92      }
93  
94      protected HttpRoutePlanner getRoutePlanner()
95      {
96          return proxyConfig.isSet() ? new ProxyRoutePlanner(proxyConfig) : null;
97      }
98  
99      /**
100      * We can override the to override the request execution behaviour. This is useful for testing, but potentially
101      * also useful in other scenarious.
102      * @return HttpRequestExecutor
103      */
104     protected HttpRequestExecutor getRequestExecutor()
105     {
106         return null;
107     }
108 
109     protected HttpClientConnectionManager getConnectionManager()
110     {
111         return null;
112     }
113 
114 }