summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/proxy/proxy_config.h2
-rw-r--r--net/proxy/proxy_service.cc33
-rw-r--r--net/proxy/proxy_service_unittest.cc206
3 files changed, 188 insertions, 53 deletions
diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h
index ec6c1fc..50d9497 100644
--- a/net/proxy/proxy_config.h
+++ b/net/proxy/proxy_config.h
@@ -92,6 +92,8 @@ class ProxyConfig {
// Indicates a list of hosts that should bypass any proxy configuration. For
// these hosts, a direct connection should always be used.
+ // The form <host>:<port> is also supported, meaning that only
+ // connections on the specified port should be direct.
std::vector<std::string> proxy_bypass;
// Indicates whether local names (no dots) bypass proxies.
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index bc4378e..4657ec9 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -578,6 +578,9 @@ bool ProxyService::ShouldBypassProxyForURL(const GURL& url) {
// percent-encoded characters.
StringToLowerASCII(&url_domain);
+ std::string url_domain_and_port = url_domain + ":"
+ + IntToString(url.EffectiveIntPort());
+
if (config_.proxy_bypass_local_names) {
if (url.host().find('.') == std::string::npos)
return true;
@@ -591,24 +594,48 @@ bool ProxyService::ShouldBypassProxyForURL(const GURL& url) {
// If no scheme is specified then it indicates that all schemes are
// allowed for the current entry. For matching this we just use
// the protocol scheme of the url passed in.
- if (bypass_url_domain.find("://") == std::string::npos) {
+ size_t scheme_colon = bypass_url_domain.find("://");
+ if (scheme_colon == std::string::npos) {
std::string bypass_url_domain_with_scheme = url.scheme();
+ scheme_colon = bypass_url_domain_with_scheme.length();
bypass_url_domain_with_scheme += "://";
bypass_url_domain_with_scheme += bypass_url_domain;
bypass_url_domain = bypass_url_domain_with_scheme;
}
+ std::string* url_compare_reference = &url_domain;
+ size_t port_colon = bypass_url_domain.rfind(":");
+ if (port_colon > scheme_colon) {
+ // If our match pattern includes a colon followed by a digit,
+ // and either it's preceded by ']' (IPv6 with port)
+ // or has no other colon (IPv4),
+ // then match against <domain>:<port>.
+ // TODO(sdoyon): straighten this out, in particular the IPv6 brackets,
+ // and do the parsing in ProxyConfig when we do the CIDR matching
+ // mentioned below.
+ std::string::const_iterator domain_begin =
+ bypass_url_domain.begin() + scheme_colon + 3; // after ://
+ std::string::const_iterator port_iter =
+ bypass_url_domain.begin() + port_colon;
+ std::string::const_iterator end = bypass_url_domain.end();
+ if ((port_iter + 1) < end && IsAsciiDigit(*(port_iter + 1)) &&
+ (*(port_iter - 1) == ']' ||
+ std::find(domain_begin, port_iter, ':') == port_iter))
+ url_compare_reference = &url_domain_and_port;
+ }
StringToLowerASCII(&bypass_url_domain);
- if (MatchPattern(url_domain, bypass_url_domain))
+ if (MatchPattern(*url_compare_reference, bypass_url_domain))
return true;
// Some systems (the Mac, for example) allow CIDR-style specification of
// proxy bypass for IP-specified hosts (e.g. "10.0.0.0/8"; see
// http://www.tcd.ie/iss/internet/osx_proxy.php for a real-world example).
// That's kinda cool so we'll provide that for everyone.
- // TODO(avi): implement here
+ // TODO(avi): implement here. See: http://crbug.com/9835.
+ // IP addresses ought to be canonicalized for comparison (whether
+ // with CIDR, port, or IP address alone).
}
return false;
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc
index 68d4be5..a2b33d4 100644
--- a/net/proxy/proxy_service_unittest.cc
+++ b/net/proxy/proxy_service_unittest.cc
@@ -686,83 +686,189 @@ TEST(ProxyServiceTest, ProxyFallback_BadConfig) {
TEST(ProxyServiceTest, ProxyBypassList) {
// Test what happens when a proxy bypass list is specified.
+ net::ProxyInfo info;
net::ProxyConfig config;
config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090");
config.auto_detect = false;
config.proxy_bypass_local_names = true;
- SyncProxyService service(new MockProxyConfigService(config),
- new MockProxyResolver());
- GURL url("http://www.google.com/");
- // Get the proxy information.
- net::ProxyInfo info;
- int rv = service.ResolveProxy(url, &info);
- EXPECT_EQ(rv, net::OK);
- EXPECT_FALSE(info.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver());
+ GURL url("http://www.google.com/");
+ // Get the proxy information.
+ int rv = service.ResolveProxy(url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_FALSE(info.is_direct());
+ }
- SyncProxyService service1(new MockProxyConfigService(config),
- new MockProxyResolver());
- GURL test_url1("local");
- net::ProxyInfo info1;
- rv = service1.ResolveProxy(test_url1, &info1);
- EXPECT_EQ(rv, net::OK);
- EXPECT_TRUE(info1.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver());
+ GURL test_url("local");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
config.proxy_bypass.clear();
config.proxy_bypass.push_back("*.org");
config.proxy_bypass_local_names = true;
- SyncProxyService service2(new MockProxyConfigService(config),
- new MockProxyResolver);
- GURL test_url2("http://www.webkit.org");
- net::ProxyInfo info2;
- rv = service2.ResolveProxy(test_url2, &info2);
- EXPECT_EQ(rv, net::OK);
- EXPECT_TRUE(info2.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://www.webkit.org");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
config.proxy_bypass.clear();
config.proxy_bypass.push_back("*.org");
config.proxy_bypass.push_back("7*");
config.proxy_bypass_local_names = true;
- SyncProxyService service3(new MockProxyConfigService(config),
- new MockProxyResolver);
- GURL test_url3("http://74.125.19.147");
- net::ProxyInfo info3;
- rv = service3.ResolveProxy(test_url3, &info3);
- EXPECT_EQ(rv, net::OK);
- EXPECT_TRUE(info3.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://74.125.19.147");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
config.proxy_bypass.clear();
config.proxy_bypass.push_back("*.org");
config.proxy_bypass_local_names = true;
- SyncProxyService service4(new MockProxyConfigService(config),
- new MockProxyResolver);
- GURL test_url4("http://www.msn.com");
- net::ProxyInfo info4;
- rv = service4.ResolveProxy(test_url4, &info4);
- EXPECT_EQ(rv, net::OK);
- EXPECT_FALSE(info4.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://www.msn.com");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_FALSE(info.is_direct());
+ }
config.proxy_bypass.clear();
config.proxy_bypass.push_back("*.MSN.COM");
config.proxy_bypass_local_names = true;
- SyncProxyService service5(new MockProxyConfigService(config),
- new MockProxyResolver);
- GURL test_url5("http://www.msnbc.msn.com");
- net::ProxyInfo info5;
- rv = service5.ResolveProxy(test_url5, &info5);
- EXPECT_EQ(rv, net::OK);
- EXPECT_TRUE(info5.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://www.msnbc.msn.com");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
config.proxy_bypass.clear();
config.proxy_bypass.push_back("*.msn.com");
config.proxy_bypass_local_names = true;
- SyncProxyService service6(new MockProxyConfigService(config),
- new MockProxyResolver);
- GURL test_url6("HTTP://WWW.MSNBC.MSN.COM");
- net::ProxyInfo info6;
- rv = service6.ResolveProxy(test_url6, &info6);
- EXPECT_EQ(rv, net::OK);
- EXPECT_TRUE(info6.is_direct());
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("HTTP://WWW.MSNBC.MSN.COM");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+}
+
+TEST(ProxyServiceTest, ProxyBypassListWithPorts) {
+ // Test port specification in bypass list entries.
+ net::ProxyInfo info;
+ net::ProxyConfig config;
+ config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090");
+ config.auto_detect = false;
+ config.proxy_bypass_local_names = false;
+
+ config.proxy_bypass.clear();
+ config.proxy_bypass.push_back("*.example.com:99");
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ {
+ GURL test_url("http://www.example.com:99");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+ {
+ GURL test_url("http://www.example.com:100");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_FALSE(info.is_direct());
+ }
+ {
+ GURL test_url("http://www.example.com");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_FALSE(info.is_direct());
+ }
+ }
+
+ config.proxy_bypass.clear();
+ config.proxy_bypass.push_back("*.example.com:80");
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://www.example.com");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+
+ config.proxy_bypass.clear();
+ config.proxy_bypass.push_back("*.example.com");
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ GURL test_url("http://www.example.com:99");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+
+ // IPv6 with port.
+ config.proxy_bypass.clear();
+ config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99");
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ {
+ GURL test_url("http://[3ffe:2a00:100:7031::1]:99/");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+ {
+ GURL test_url("http://[3ffe:2a00:100:7031::1]/");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_FALSE(info.is_direct());
+ }
+ }
+
+ // IPv6 without port. The bypass entry ought to work without the
+ // brackets, but the bypass matching logic in ProxyService is
+ // currently limited.
+ config.proxy_bypass.clear();
+ config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]");
+ {
+ SyncProxyService service(new MockProxyConfigService(config),
+ new MockProxyResolver);
+ {
+ GURL test_url("http://[3ffe:2a00:100:7031::1]:99/");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+ {
+ GURL test_url("http://[3ffe:2a00:100:7031::1]/");
+ int rv = service.ResolveProxy(test_url, &info);
+ EXPECT_EQ(rv, net::OK);
+ EXPECT_TRUE(info.is_direct());
+ }
+ }
}
TEST(ProxyServiceTest, PerProtocolProxyTests) {