Skip to content

Commit 68d3360

Browse files
authored
Merge pull request #12 from batterseapower/master
[JENKINS-39267] Honour the no_proxy setting when connecting to BitBucket
2 parents e80535f + 04740e6 commit 68d3360

File tree

2 files changed

+105
-49
lines changed

2 files changed

+105
-49
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/BitbucketCloudApiClient.java

+67-34
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,25 @@
2626
import java.io.IOException;
2727
import java.io.InputStream;
2828
import java.io.UnsupportedEncodingException;
29+
import java.net.InetSocketAddress;
30+
import java.net.Proxy;
2931
import java.net.URLEncoder;
3032
import java.util.ArrayList;
3133
import java.util.Collections;
3234
import java.util.List;
3335
import java.util.logging.Level;
3436
import java.util.logging.Logger;
3537

38+
import org.apache.commons.httpclient.HostConfiguration;
3639
import org.apache.commons.httpclient.HttpClient;
3740
import org.apache.commons.httpclient.HttpException;
3841
import org.apache.commons.httpclient.HttpStatus;
42+
import org.apache.commons.httpclient.HttpMethod;
43+
import org.apache.commons.httpclient.HttpState;
3944
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
4045
import org.apache.commons.httpclient.NameValuePair;
4146
import org.apache.commons.httpclient.UsernamePasswordCredentials;
47+
import org.apache.commons.httpclient.URIException;
4248
import org.apache.commons.httpclient.auth.AuthScope;
4349
import org.apache.commons.httpclient.methods.DeleteMethod;
4450
import org.apache.commons.httpclient.methods.GetMethod;
@@ -85,10 +91,10 @@ public class BitbucketCloudApiClient implements BitbucketApi {
8591
private static final String V2_TEAMS_API_BASE_URL = "https://bitbucket.org/api/2.0/teams/";
8692
private static final int MAX_PAGES = 100;
8793
private HttpClient client;
88-
private static MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
89-
private String owner;
90-
private String repositoryName;
91-
private UsernamePasswordCredentials credentials;
94+
private static final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
95+
private final String owner;
96+
private final String repositoryName;
97+
private final UsernamePasswordCredentials credentials;
9298

9399
static {
94100
connectionManager.getParams().setDefaultMaxConnectionsPerHost(20);
@@ -98,6 +104,8 @@ public class BitbucketCloudApiClient implements BitbucketApi {
98104
public BitbucketCloudApiClient(String username, String password, String owner, String repositoryName) {
99105
if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) {
100106
this.credentials = new UsernamePasswordCredentials(username, password);
107+
} else {
108+
this.credentials = null;
101109
}
102110
this.owner = owner;
103111
this.repositoryName = repositoryName;
@@ -106,6 +114,8 @@ public BitbucketCloudApiClient(String username, String password, String owner, S
106114
public BitbucketCloudApiClient(String owner, String repositoryName, StandardUsernamePasswordCredentials creds) {
107115
if (creds != null) {
108116
this.credentials = new UsernamePasswordCredentials(creds.getUsername(), Secret.toString(creds.getPassword()));
117+
} else {
118+
this.credentials = null;
109119
}
110120
this.owner = owner;
111121
this.repositoryName = repositoryName;
@@ -391,41 +401,62 @@ public List<BitbucketCloudRepository> getRepositories() {
391401
}
392402

393403
private synchronized HttpClient getHttpClient() {
404+
if (this.client == null) {
405+
HttpClient client = new HttpClient(connectionManager);
406+
client.getParams().setConnectionManagerTimeout(10 * 1000);
407+
client.getParams().setSoTimeout(60 * 1000);
394408

395-
if (this.client != null) return this.client;
409+
client.getState().setCredentials(AuthScope.ANY, credentials);
410+
client.getParams().setAuthenticationPreemptive(true);
396411

397-
this.client = new HttpClient(connectionManager);
398-
this.client.getParams().setConnectionManagerTimeout(10 * 1000);
399-
this.client.getParams().setSoTimeout(60 * 1000);
412+
this.client = client;
413+
}
400414

415+
return this.client;
416+
}
417+
418+
private static int executeMethod(HttpClient client, HttpMethod method) throws IOException {
401419
Jenkins jenkins = Jenkins.getInstance();
402-
ProxyConfiguration proxy = null;
420+
ProxyConfiguration proxyConfig = null;
403421
if (jenkins != null) {
404-
proxy = jenkins.proxy;
422+
proxyConfig = jenkins.proxy;
405423
}
406-
if (proxy != null) {
407-
LOGGER.info("Jenkins proxy: " + proxy.name + ":" + proxy.port);
408-
this.client.getHostConfiguration().setProxy(proxy.name, proxy.port);
409-
String username = proxy.getUserName();
410-
String password = proxy.getPassword();
424+
425+
Proxy proxy = Proxy.NO_PROXY;
426+
if (proxyConfig != null) {
427+
proxy = proxyConfig.createProxy(getMethodHost(method));
428+
}
429+
430+
if (proxy.type() != Proxy.Type.DIRECT) {
431+
final InetSocketAddress proxyAddress = (InetSocketAddress)proxy.address();
432+
LOGGER.fine("Jenkins proxy: " + proxy.address());
433+
434+
final HostConfiguration hc = new HostConfiguration(client.getHostConfiguration());
435+
hc.setProxy(proxyAddress.getHostString(), proxyAddress.getPort());
436+
437+
String username = proxyConfig.getUserName();
438+
String password = proxyConfig.getPassword();
411439
if (username != null && !"".equals(username.trim())) {
412-
LOGGER.info("Using proxy authentication (user=" + username + ")");
413-
this.client.getState().setProxyCredentials(AuthScope.ANY,
414-
new UsernamePasswordCredentials(username, password));
440+
LOGGER.fine("Using proxy authentication (user=" + username + ")");
441+
442+
final HttpState state = new HttpState();
443+
state.setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
444+
return client.executeMethod(hc, method, state);
445+
} else {
446+
return client.executeMethod(hc, method);
415447
}
448+
} else {
449+
return client.executeMethod(method);
416450
}
417-
return this.client;
418451
}
419452

420453
private String getRequest(String path) {
421-
HttpClient client = getHttpClient();
422-
client.getState().setCredentials(AuthScope.ANY, credentials);
423454
GetMethod httpget = new GetMethod(path);
424-
client.getParams().setAuthenticationPreemptive(true);
455+
HttpClient client = getHttpClient();
425456
String response = null;
426457
InputStream responseBodyAsStream = null;
427458
try {
428-
client.executeMethod(httpget);
459+
executeMethod(client, httpget);
429460
responseBodyAsStream = httpget.getResponseBodyAsStream();
430461
response = IOUtils.toString(responseBodyAsStream, "UTF-8");
431462
if (httpget.getStatusCode() != HttpStatus.SC_OK) {
@@ -448,12 +479,10 @@ private String getRequest(String path) {
448479
}
449480

450481
private int getRequestStatus(String path) {
451-
HttpClient client = getHttpClient();
452-
client.getState().setCredentials(AuthScope.ANY, credentials);
453482
GetMethod httpget = new GetMethod(path);
454-
client.getParams().setAuthenticationPreemptive(true);
483+
HttpClient client = getHttpClient();
455484
try {
456-
client.executeMethod(httpget);
485+
executeMethod(client, httpget);
457486
return httpget.getStatusCode();
458487
} catch (HttpException e) {
459488
LOGGER.log(Level.SEVERE, "Communication error", e);
@@ -465,13 +494,19 @@ private int getRequestStatus(String path) {
465494
return -1;
466495
}
467496

497+
private static String getMethodHost(HttpMethod method) {
498+
try {
499+
return method.getURI().getHost();
500+
} catch (URIException e) {
501+
throw new IllegalStateException("Could not obtain host part for method " + method, e);
502+
}
503+
}
504+
468505
private void deleteRequest(String path) {
469-
HttpClient client = getHttpClient();
470-
client.getState().setCredentials(AuthScope.ANY, credentials);
471506
DeleteMethod httppost = new DeleteMethod(path);
472-
client.getParams().setAuthenticationPreemptive(true);
507+
HttpClient client = getHttpClient();
473508
try {
474-
client.executeMethod(httppost);
509+
executeMethod(client, httppost);
475510
if (httppost.getStatusCode() != HttpStatus.SC_NO_CONTENT) {
476511
throw new BitbucketRequestException(httppost.getStatusCode(), "HTTP request error. Status: " + httppost.getStatusCode() + ": " + httppost.getStatusText());
477512
}
@@ -484,12 +519,10 @@ private void deleteRequest(String path) {
484519

485520
private String postRequest(PostMethod httppost) throws UnsupportedEncodingException {
486521
HttpClient client = getHttpClient();
487-
client.getState().setCredentials(AuthScope.ANY, credentials);
488-
client.getParams().setAuthenticationPreemptive(true);
489522
String response = "";
490523
InputStream responseBodyAsStream = null;
491524
try {
492-
client.executeMethod(httppost);
525+
executeMethod(client, httppost);
493526
responseBodyAsStream = httppost.getResponseBodyAsStream();
494527
response = IOUtils.toString(responseBodyAsStream, "UTF-8");
495528
if (httppost.getStatusCode() != HttpStatus.SC_OK && httppost.getStatusCode() != HttpStatus.SC_CREATED) {

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java

+38-15
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.io.IOException;
2727
import java.io.InputStream;
2828
import java.io.UnsupportedEncodingException;
29+
import java.net.InetSocketAddress;
30+
import java.net.Proxy;
2931
import java.util.ArrayList;
3032
import java.util.Collections;
3133
import java.util.List;
@@ -35,8 +37,10 @@
3537
import org.apache.commons.httpclient.HttpClient;
3638
import org.apache.commons.httpclient.HttpException;
3739
import org.apache.commons.httpclient.HttpStatus;
40+
import org.apache.commons.httpclient.HttpMethod;
3841
import org.apache.commons.httpclient.NameValuePair;
3942
import org.apache.commons.httpclient.UsernamePasswordCredentials;
43+
import org.apache.commons.httpclient.URIException;
4044
import org.apache.commons.httpclient.auth.AuthScope;
4145
import org.apache.commons.httpclient.methods.GetMethod;
4246
import org.apache.commons.httpclient.methods.PostMethod;
@@ -368,9 +372,9 @@ private <T> T parse(String response, Class<T> clazz) throws IOException {
368372
}
369373

370374
private String getRequest(String path) {
371-
HttpClient client = getHttpClient();
372-
client.getState().setCredentials(AuthScope.ANY, credentials);
373375
GetMethod httpget = new GetMethod(this.baseURL + path);
376+
HttpClient client = getHttpClient(getMethodHost(httpget));
377+
client.getState().setCredentials(AuthScope.ANY, credentials);
374378
client.getParams().setAuthenticationPreemptive(true);
375379
String response = null;
376380
InputStream responseBodyAsStream = null;
@@ -397,35 +401,46 @@ private String getRequest(String path) {
397401
return response;
398402
}
399403

400-
private HttpClient getHttpClient() {
404+
private HttpClient getHttpClient(String host) {
401405
HttpClient client = new HttpClient();
402406

403407
client.getParams().setConnectionManagerTimeout(10 * 1000);
404408
client.getParams().setSoTimeout(60 * 1000);
405409

410+
setClientProxyParams(host, client);
411+
return client;
412+
}
413+
414+
private static void setClientProxyParams(String host, HttpClient client) {
406415
Jenkins jenkins = Jenkins.getInstance();
407-
ProxyConfiguration proxy = null;
416+
ProxyConfiguration proxyConfig = null;
408417
if (jenkins != null) {
409-
proxy = jenkins.proxy;
418+
proxyConfig = jenkins.proxy;
419+
}
420+
421+
Proxy proxy = Proxy.NO_PROXY;
422+
if (proxyConfig != null) {
423+
proxy = proxyConfig.createProxy(host);
410424
}
411-
if (proxy != null) {
412-
LOGGER.info("Jenkins proxy: " + proxy.name + ":" + proxy.port);
413-
client.getHostConfiguration().setProxy(proxy.name, proxy.port);
414-
String username = proxy.getUserName();
415-
String password = proxy.getPassword();
425+
426+
if (proxy.type() != Proxy.Type.DIRECT) {
427+
final InetSocketAddress proxyAddress = (InetSocketAddress)proxy.address();
428+
LOGGER.fine("Jenkins proxy: " + proxy.address());
429+
client.getHostConfiguration().setProxy(proxyAddress.getHostString(), proxyAddress.getPort());
430+
String username = proxyConfig.getUserName();
431+
String password = proxyConfig.getPassword();
416432
if (username != null && !"".equals(username.trim())) {
417-
LOGGER.info("Using proxy authentication (user=" + username + ")");
433+
LOGGER.fine("Using proxy authentication (user=" + username + ")");
418434
client.getState().setProxyCredentials(AuthScope.ANY,
419435
new UsernamePasswordCredentials(username, password));
420436
}
421437
}
422-
return client;
423438
}
424439

425440
private int getRequestStatus(String path) {
426-
HttpClient client = getHttpClient();
427-
client.getState().setCredentials(AuthScope.ANY, credentials);
428441
GetMethod httpget = new GetMethod(this.baseURL + path);
442+
HttpClient client = getHttpClient(getMethodHost(httpget));
443+
client.getState().setCredentials(AuthScope.ANY, credentials);
429444
client.getParams().setAuthenticationPreemptive(true);
430445
try {
431446
client.executeMethod(httpget);
@@ -440,6 +455,14 @@ private int getRequestStatus(String path) {
440455
return -1;
441456
}
442457

458+
private static String getMethodHost(HttpMethod method) {
459+
try {
460+
return method.getURI().getHost();
461+
} catch (URIException e) {
462+
throw new IllegalStateException("Could not obtain host part for method " + method, e);
463+
}
464+
}
465+
443466
private <T> String serialize(T o) throws IOException {
444467
ObjectMapper mapper = new ObjectMapper();
445468
return mapper.writeValueAsString(o);
@@ -466,7 +489,7 @@ private String nameValueToJson(NameValuePair[] params) {
466489
}
467490

468491
private String postRequest(PostMethod httppost) throws UnsupportedEncodingException {
469-
HttpClient client = getHttpClient();
492+
HttpClient client = getHttpClient(getMethodHost(httppost));
470493
client.getState().setCredentials(AuthScope.ANY, credentials);
471494
client.getParams().setAuthenticationPreemptive(true);
472495
String response = null;

0 commit comments

Comments
 (0)