diff options
author | Kristina Chodorow <kchodorow@google.com> | 2016-01-08 18:44:20 +0000 |
---|---|---|
committer | Damien Martin-Guillerez <dmarting@google.com> | 2016-01-11 09:42:01 +0000 |
commit | 92beaeeace4c32b9cda19b39581ec823202fcf1f (patch) | |
tree | efc587deb69aacee66a967f536a57dfec6e130dc /src | |
parent | 90a8d6c04f35a5f2ea1417bc9cf7517c400ecfc8 (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.java | 64 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/bazel/repository/HttpDownloaderTest.java | 31 |
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"); } } |