aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Kristina Chodorow <kchodorow@google.com>2016-01-08 18:44:20 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-01-11 09:42:01 +0000
commit92beaeeace4c32b9cda19b39581ec823202fcf1f (patch)
treeefc587deb69aacee66a967f536a57dfec6e130dc /src
parent90a8d6c04f35a5f2ea1417bc9cf7517c400ecfc8 (diff)
Add auth support for proxy downloads
Should fix #587. RELNOTES: Support for downloading remote resources through proxies by setting HTTP_PROXY (or HTTPS_PROXY). -- Change-Id: I4ae18c4f1a9e911e538efd446323e279e9776eec Reviewed-on: https://github.com/bazelbuild/bazel/pull/759 MOS_MIGRATED_REVID=111708438
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloader.java64
-rw-r--r--src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java31
2 files changed, 74 insertions, 21 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloader.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloader.java
index e75c7daeb5..9723314f60 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloader.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/HttpDownloader.java
@@ -32,8 +32,10 @@ import com.google.devtools.build.skyframe.SkyFunctionException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@@ -42,6 +44,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.annotation.Nullable;
@@ -209,31 +213,55 @@ public class HttpDownloader {
return Proxy.NO_PROXY;
}
- // Split the proxyAddress into the protocol, address, and optional port. This does not use the
- // URL class to avoid the DNS resolution it performs on creation.
- int protocolIndex = proxyAddress.indexOf(':');
- if (protocolIndex == -1) {
- throw new IOException("No proxy protocol found for " + proxyAddress);
+ // Here there be dragons.
+ Pattern urlPattern =
+ Pattern.compile("^(https?)://(?:([^:@]+?)(?::([^@]+?))?@)?(?:[^:]+)(?::(\\d+))?$");
+ Matcher matcher = urlPattern.matcher(proxyAddress);
+ if (!matcher.matches()) {
+ throw new IOException("Proxy address " + proxyAddress + " is not a valid URL");
}
+
+ String protocol = matcher.group(1);
+ final String username = matcher.group(2);
+ final String password = matcher.group(3);
+ String port = matcher.group(4);
+
boolean https;
- String protocol = proxyAddress.substring(0, protocolIndex);
- if (protocol.equals("https")) {
- https = true;
- } else if (protocol.equals("http")) {
- https = false;
- } else {
- throw new IOException("Invalid proxy protocol for " + proxyAddress);
+ switch (protocol) {
+ case "https":
+ https = true;
+ break;
+ case "http":
+ https = false;
+ break;
+ default:
+ throw new IOException("Invalid proxy protocol for " + proxyAddress);
}
- int portIndex = proxyAddress.lastIndexOf(':');
- if (protocolIndex == portIndex) {
- // No port set, just the http: colon.
+
+ if (username != null) {
+ if (password == null) {
+ throw new IOException("No password given for proxy " + proxyAddress);
+ }
+ System.setProperty(protocol + ".proxyUser", username);
+ System.setProperty(protocol + ".proxyPassword", password);
+
+ Authenticator.setDefault(
+ new Authenticator() {
+ public PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password.toCharArray());
+ }
+ });
+ }
+
+ if (port == null) {
return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, https ? 443 : 80));
}
try {
- return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
- proxyAddress.substring(0, portIndex),
- Integer.parseInt(proxyAddress.substring(portIndex + 1))));
+ return new Proxy(
+ Proxy.Type.HTTP,
+ new InetSocketAddress(
+ proxyAddress.substring(0, proxyAddress.lastIndexOf(':')), Integer.parseInt(port)));
} catch (NumberFormatException e) {
throw new IOException("Error parsing proxy port: " + proxyAddress);
}
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java
index 93afe43516..c30ec580ab 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java
@@ -64,7 +64,7 @@ public class HttpDownloaderTest {
HttpDownloader.createProxy("my.example.com");
fail("Expected protocol error");
} catch (IOException e) {
- assertThat(e.getMessage()).contains("No proxy protocol found");
+ assertThat(e.getMessage()).contains("Proxy address my.example.com is not a valid URL");
}
}
@@ -74,7 +74,7 @@ public class HttpDownloaderTest {
HttpDownloader.createProxy("my.example.com:12345");
fail("Expected protocol error");
} catch (IOException e) {
- assertThat(e.getMessage()).contains("Invalid proxy protocol");
+ assertThat(e.getMessage()).contains("Proxy address my.example.com:12345 is not a valid URL");
}
}
@@ -84,7 +84,32 @@ public class HttpDownloaderTest {
HttpDownloader.createProxy("http://my.example.com:foo");
fail("Should have thrown an error for invalid port");
} catch (IOException e) {
- assertThat(e.getMessage()).contains("Error parsing proxy port");
+ assertThat(e.getMessage())
+ .contains("Proxy address http://my.example.com:foo is not a valid URL");
+ }
+ }
+
+ @Test
+ public void testProxyAuth() throws Exception {
+ Proxy proxy = HttpDownloader.createProxy("http://foo:barbaz@my.example.com");
+ assertEquals(Proxy.Type.HTTP, proxy.type());
+ assertThat(proxy.toString()).endsWith(":80");
+ assertEquals(System.getProperty("http.proxyUser"), "foo");
+ assertEquals(System.getProperty("http.proxyPassword"), "barbaz");
+
+ proxy = HttpDownloader.createProxy("https://biz:bat@my.example.com");
+ assertThat(proxy.toString()).endsWith(":443");
+ assertEquals(System.getProperty("https.proxyUser"), "biz");
+ assertEquals(System.getProperty("https.proxyPassword"), "bat");
+ }
+
+ @Test
+ public void testInvalidAuth() throws Exception {
+ try {
+ HttpDownloader.createProxy("http://foo@my.example.com");
+ fail("Should have thrown an error for invalid auth");
+ } catch (IOException e) {
+ assertThat(e.getMessage()).contains("No password given for proxy");
}
}