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 com.google.common.base.Supplier;
6 import com.google.common.base.Suppliers;
7 import org.apache.http.HttpHeaders;
8 import org.apache.http.HttpHost;
9 import org.apache.http.auth.AuthScope;
10 import org.apache.http.auth.Credentials;
11 import org.apache.http.auth.MalformedChallengeException;
12 import org.apache.http.auth.UsernamePasswordCredentials;
13 import org.apache.http.client.AuthCache;
14 import org.apache.http.client.CredentialsProvider;
15 import org.apache.http.client.config.CookieSpecs;
16 import org.apache.http.client.config.RequestConfig;
17 import org.apache.http.client.protocol.HttpClientContext;
18 import org.apache.http.conn.HttpClientConnectionManager;
19 import org.apache.http.conn.routing.HttpRoutePlanner;
20 import org.apache.http.impl.auth.BasicScheme;
21 import org.apache.http.impl.client.BasicCredentialsProvider;
22 import org.apache.http.impl.client.CloseableHttpClient;
23 import org.apache.http.impl.client.HttpClients;
24 import org.apache.http.message.BasicHeader;
25 import org.apache.http.protocol.HttpRequestExecutor;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29
30
31
32
33 public class HttpClientRequestFactory implements NonMarshallingRequestFactory<HttpClientRequest<?, ?>> {
34 private static final Logger log = LoggerFactory.getLogger(HttpClientRequestFactory.class);
35
36 private final Supplier<ProxyConfig> proxyConfigSupplier;
37
38 public HttpClientRequestFactory() {
39
40
41 proxyConfigSupplier = Suppliers.memoize(SystemPropertiesProxyConfig::new);
42 }
43
44 public HttpClientRequestFactory(final ProxyConfig proxyConfig) {
45 this.proxyConfigSupplier = () -> proxyConfig;
46 }
47
48
49
50
51 public HttpClientRequest createRequest(final MethodType methodType, final String url) {
52 log.debug("Creating HttpClientRequest with proxy config:", proxyConfigSupplier.get());
53
54 final CloseableHttpClient httpClient = createHttpClient();
55 final boolean requiresAuthentication = ProxyUtil.requiresAuthentication(proxyConfigSupplier.get(), url);
56 final HttpClientContext clientContext = createClientContext(requiresAuthentication);
57 return new HttpClientRequest(httpClient, clientContext, methodType, url);
58 }
59
60 protected CloseableHttpClient createHttpClient() {
61 return HttpClients.custom()
62 .useSystemProperties()
63 .setRoutePlanner(getRoutePlanner())
64 .setRequestExecutor(getRequestExecutor())
65 .setConnectionManager(getConnectionManager())
66 .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build())
67 .build();
68 }
69
70 protected HttpClientContext createClientContext() {
71 return createClientContext(proxyConfigSupplier.get().requiresAuthentication());
72 }
73
74 protected HttpClientContext createClientContext(boolean requiresAuthentication) {
75 final HttpClientContext httpClientContext = HttpClientContext.create();
76 final AuthCache authCache = new AllPortsAuthCache();
77 final CredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
78 final ProxyConfig proxyConfig = this.proxyConfigSupplier.get();
79
80 if (requiresAuthentication) {
81 HttpHost proxyHost = new HttpHost(proxyConfig.getHost(), proxyConfig.getPort());
82 final AuthScope proxyAuthScope = new AuthScope(proxyHost);
83 final Credentials proxyCredentials = new UsernamePasswordCredentials(proxyConfig.getUser(),
84 proxyConfig.getPassword());
85 basicCredentialsProvider.setCredentials(proxyAuthScope, proxyCredentials);
86
87
88 BasicScheme proxyScheme = new BasicScheme();
89 try {
90 proxyScheme.processChallenge(
91 new BasicHeader(HttpHeaders.PROXY_AUTHENTICATE, "Basic "));
92 } catch (MalformedChallengeException e) {
93 throw new IllegalStateException(e);
94 }
95 authCache.put(proxyHost, proxyScheme);
96 }
97
98 httpClientContext.setCredentialsProvider(basicCredentialsProvider);
99 httpClientContext.setAuthCache(authCache);
100 return httpClientContext;
101 }
102
103 public boolean supportsHeader() {
104 return true;
105 }
106
107 protected HttpRoutePlanner getRoutePlanner() {
108 return proxyConfigSupplier.get().isSet() ? new ProxyRoutePlanner(proxyConfigSupplier.get()) : null;
109 }
110
111
112
113
114
115
116
117 protected HttpRequestExecutor getRequestExecutor() {
118 return null;
119 }
120
121 protected HttpClientConnectionManager getConnectionManager() {
122 return null;
123 }
124
125 }