6737819: sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost
Summary: Move default nonProxyHosts from hardcoded to property default value
Reviewed-by: chegar
--- a/jdk/src/share/classes/java/net/doc-files/net-properties.html Wed Sep 16 09:23:50 2009 -0700
+++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html Fri Sep 18 10:51:44 2009 +0200
@@ -71,12 +71,12 @@
<LI><P>HTTP</P>
<P>The following proxy settings are used by the HTTP protocol handler.</P>
<UL>
- <LI><P><B>http.proxyHost</FONT></B> (default: <none>)<BR>
+ <LI><P><B>http.proxyHost</B> (default: <none>)<BR>
The hostname, or address, of the proxy server
</P>
<LI><P><B>http.proxyPort</B> (default: 80)<BR>
The port number of the proxy server.</P>
- <LI><P><B>http.nonProxyHosts</B> (default: <none>)<BR>
+ <LI><P><B>http.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts,
@@ -86,7 +86,8 @@
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.</P>
- </UL>
+ <P>The default value excludes all common variations of the loopback address.</P>
+ </UL>
<LI><P>HTTPS<BR>This is HTTP over SSL, a secure version of HTTP
mainly used when confidentiality (like on payment sites) is needed.</P>
<P>The following proxy settings are used by the HTTPS protocol handler.</P>
@@ -107,7 +108,7 @@
</P>
<LI><P><B>ftp.proxyPort</B> (default: 80)<BR>
The port number of the proxy server.</P>
- <LI><P><B>ftp.nonProxyHosts</B> (default: <none>)<BR>
+ <LI><P><B>ftp.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts, separated by
@@ -117,6 +118,7 @@
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.</P>
+ <P>The default value excludes all common variations of the loopback address.</P>
</UL>
<LI><P>SOCKS<BR>This is another type of proxy. It allows for lower
level type of tunneling since it works at the TCP level. In effect,
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Wed Sep 16 09:23:50 2009 -0700
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Fri Sep 18 10:51:44 2009 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,9 @@
package sun.net.spi;
-import sun.net.www.http.*;
import sun.net.NetProperties;
import java.net.*;
import java.util.*;
-import java.util.regex.*;
import java.io.*;
import sun.misc.RegexpPool;
import java.security.AccessController;
@@ -102,17 +100,22 @@
*/
static class NonProxyInfo {
+ // Default value for nonProxyHosts, this provides backward compatibility
+ // by excluding localhost and its litteral notations.
+ static final String defStringVal = "localhost|127.*|[::1]";
+
String hostsSource;
RegexpPool hostsPool;
- String property;
+ final String property;
+ final String defaultVal;
+ static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
+ static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
- static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
- static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
-
- NonProxyInfo(String p, String s, RegexpPool pool) {
+ NonProxyInfo(String p, String s, RegexpPool pool, String d) {
property = p;
hostsSource = s;
hostsPool = pool;
+ defaultVal = d;
}
}
@@ -130,7 +133,6 @@
}
String protocol = uri.getScheme();
String host = uri.getHost();
- int port = uri.getPort();
if (host == null) {
// This is a hack to ensure backward compatibility in two
@@ -149,11 +151,6 @@
}
i = auth.lastIndexOf(':');
if (i >= 0) {
- try {
- port = Integer.parseInt(auth.substring(i+1));
- } catch (NumberFormatException e) {
- port = -1;
- }
auth = auth.substring(0,i);
}
host = auth;
@@ -165,13 +162,6 @@
}
List<Proxy> proxyl = new ArrayList<Proxy>(1);
- // special case localhost and loopback addresses to
- // not go through proxy
- if (isLoopback(host)) {
- proxyl.add(Proxy.NO_PROXY);
- return proxyl;
- }
-
NonProxyInfo pinfo = null;
if ("http".equalsIgnoreCase(protocol)) {
@@ -244,9 +234,14 @@
nphosts = NetProperties.get(nprop.property);
synchronized (nprop) {
if (nphosts == null) {
- nprop.hostsSource = null;
- nprop.hostsPool = null;
- } else {
+ if (nprop.defaultVal != null) {
+ nphosts = nprop.defaultVal;
+ } else {
+ nprop.hostsSource = null;
+ nprop.hostsPool = null;
+ }
+ }
+ if (nphosts != null) {
if (!nphosts.equals(nprop.hostsSource)) {
RegexpPool pool = new RegexpPool();
StringTokenizer st = new StringTokenizer(nphosts, "|", false);
@@ -334,107 +329,6 @@
}
}
- private boolean isLoopback(String host) {
- if (host == null || host.length() == 0)
- return false;
-
- if (host.equalsIgnoreCase("localhost"))
- return true;
-
- /* The string could represent a numerical IP address.
- * For IPv4 addresses, check whether it starts with 127.
- * For IPv6 addresses, check whether it is ::1 or its equivalent.
- * Don't check IPv4-mapped or IPv4-compatible addresses
- */
-
- if (host.startsWith("127.")) {
- // possible IPv4 loopback address
- int p = 4;
- int q;
- int n = host.length();
- // Per RFC2732: At most three digits per byte
- // Further constraint: Each element fits in a byte
- if ((q = scanByte(host, p, n)) <= p) return false; p = q;
- if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q;
- if ((q = scanByte(host, p, n)) <= p) return false; p = q;
- if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q;
- if ((q = scanByte(host, p, n)) <= p) return false;
- return q == n && number > 0;
- }
-
- if (host.endsWith(":1")) {
- final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
- return p6.matcher(host).matches();
- }
- return false;
- }
-
- // Character-class masks, in reverse order from RFC2396 because
- // initializers for static fields cannot make forward references.
-
- // Compute a low-order mask for the characters
- // between first and last, inclusive
- private static long lowMask(char first, char last) {
- long m = 0;
- int f = Math.max(Math.min(first, 63), 0);
- int l = Math.max(Math.min(last, 63), 0);
- for (int i = f; i <= l; i++)
- m |= 1L << i;
- return m;
- }
- // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
- // "8" | "9"
- private static final long L_DIGIT = lowMask('0', '9');
- private static final long H_DIGIT = 0L;
-
- // Scan a string of decimal digits whose value fits in a byte
- //
- private int number;
- private int scanByte(String input, int start, int n)
- {
- int p = start;
- int q = scan(input, p, n, L_DIGIT, H_DIGIT);
- if (q <= p) return q;
- number = Integer.parseInt(input.substring(p, q));
- if (number > 255) return p;
- return q;
- }
-
- // Scan a specific char: If the char at the given start position is
- // equal to c, return the index of the next char; otherwise, return the
- // start position.
- //
- private int scan(String input, int start, int end, char c) {
- if ((start < end) && (input.charAt(start) == c))
- return start + 1;
- return start;
- }
-
- // Scan chars that match the given mask pair
- //
- private int scan(String input, int start, int n, long lowMask, long highMask)
- {
- int p = start;
- while (p < n) {
- char c = input.charAt(p);
- if (match(c, lowMask, highMask)) {
- p++;
- continue;
- }
- break;
- }
- return p;
- }
-
- // Tell whether the given character is permitted by the given mask pair
- private boolean match(char c, long lowMask, long highMask) {
- if (c < 64)
- return ((1L << c) & lowMask) != 0;
- if (c < 128)
- return ((1L << (c - 64)) & highMask) != 0;
- return false;
- }
-
private native static boolean init();
private native Proxy getSystemProxy(String protocol, String host);
}
--- a/jdk/src/share/lib/net.properties Wed Sep 16 09:23:50 2009 -0700
+++ b/jdk/src/share/lib/net.properties Fri Sep 18 10:51:44 2009 +0200
@@ -32,7 +32,7 @@
#
# http.proxyHost=
# http.proxyPort=80
-# http.nonProxyHosts=localhost|127.0.0.1
+http.nonProxyHosts=localhost|127.*|[::1]
#
# HTTPS Proxy Settings. proxyHost is the name of the proxy server
# (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
@@ -49,7 +49,7 @@
#
# ftp.proxyHost=
# ftp.proxyPort=80
-# ftp.nonProxyHosts=localhost|127.0.0.1
+ftp.nonProxyHosts=localhost|127.*|[::1]
#
# Gopher Proxy settings. proxyHost is the name of the proxy server
# (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/ProxySelector/B6737819.java Fri Sep 18 10:51:44 2009 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6737819
+ * @summary sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost
+ */
+
+import java.net.ProxySelector;
+import java.net.Proxy;
+import java.net.URI;
+
+public class B6737819 {
+ private static String[] uris = {
+ "http://localhost/index.html",
+ "http://127.0.0.1/index.html",
+ "http://127.2/index.html",
+ "http://[::1]/index.html"
+ };
+ public static void main(String[] args) throws Exception {
+ System.setProperty("http.proxyHost", "myproxy");
+ System.setProperty("http.proxyPort", "8080");
+ ProxySelector sel = ProxySelector.getDefault();
+ java.util.List<Proxy> l;
+ // Default value for http.nonProxyHots should exclude all this uris
+ // from going through the HTTP proxy
+ for (String s : uris) {
+ l = sel.select(new URI(s));
+ if (l.size() == 1 && l.get(0).type() != Proxy.Type.DIRECT) {
+ throw new RuntimeException("ProxySelector returned the wrong proxy for " + s);
+ }
+ }
+ // Let's override the default nonProxyHosts and make sure we now get a
+ // HTTP proxy
+ System.setProperty("http.nonProxyHosts", "");
+ for (String s : uris) {
+ l = sel.select(new URI(s));
+ if (l.size() == 1 && l.get(0).type() != Proxy.Type.HTTP) {
+ throw new RuntimeException("ProxySelector returned the wrong proxy for " + s);
+ }
+ }
+ }
+}