Skip to content

Commit 1d67d47

Browse files
jaiforumsMichael-Mc-Mahon
authored andcommitted
8177648: getResponseCode() throws IllegalArgumentException caused by protocol error while following redirect
Reviewed-by: michaelm, chegar, dfuchs
1 parent ec24017 commit 1d67d47

File tree

5 files changed

+265
-4
lines changed

5 files changed

+265
-4
lines changed

src/java.base/share/classes/java/net/ProxySelector.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -143,7 +143,9 @@ public static void setDefault(ProxySelector ps) {
143143
* contain one element of type
144144
* {@link java.net.Proxy Proxy}
145145
* that represents a direct connection.
146-
* @throws IllegalArgumentException if the argument is null
146+
* @throws IllegalArgumentException if the argument is null or if
147+
* the protocol or host cannot be determined from the provided
148+
* {@code uri}
147149
*/
148150
public abstract List<Proxy> select(URI uri);
149151

src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.net.URI;
4545
import java.net.Proxy;
4646
import java.net.ProxySelector;
47+
import java.util.List;
4748
import java.util.StringTokenizer;
4849
import java.util.Iterator;
4950
import java.security.Permission;
@@ -242,7 +243,13 @@ public ProxySelector run() {
242243
});
243244
if (sel != null) {
244245
URI uri = sun.net.www.ParseUtil.toURI(url);
245-
Iterator<Proxy> it = sel.select(uri).iterator();
246+
final List<Proxy> proxies;
247+
try {
248+
proxies = sel.select(uri);
249+
} catch (IllegalArgumentException iae) {
250+
throw new IOException("Failed to select a proxy", iae);
251+
}
252+
final Iterator<Proxy> it = proxies.iterator();
246253
while (it.hasNext()) {
247254
p = it.next();
248255
if (p == null || p == Proxy.NO_PROXY ||

src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,13 @@ public ProxySelector run() {
11781178
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
11791179
logger.finest("ProxySelector Request for " + uri);
11801180
}
1181-
Iterator<Proxy> it = sel.select(uri).iterator();
1181+
final List<Proxy> proxies;
1182+
try {
1183+
proxies = sel.select(uri);
1184+
} catch (IllegalArgumentException iae) {
1185+
throw new IOException("Failed to select a proxy", iae);
1186+
}
1187+
final Iterator<Proxy> it = proxies.iterator();
11821188
Proxy p;
11831189
while (it.hasNext()) {
11841190
p = it.next();
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import com.sun.net.httpserver.HttpExchange;
25+
import com.sun.net.httpserver.HttpHandler;
26+
import com.sun.net.httpserver.HttpServer;
27+
import org.testng.Assert;
28+
import org.testng.annotations.AfterTest;
29+
import org.testng.annotations.BeforeTest;
30+
import org.testng.annotations.Test;
31+
import sun.net.spi.DefaultProxySelector;
32+
33+
import java.io.IOException;
34+
import java.net.HttpURLConnection;
35+
import java.net.InetAddress;
36+
import java.net.InetSocketAddress;
37+
import java.net.Proxy;
38+
import java.net.ProxySelector;
39+
import java.net.URI;
40+
import java.net.URISyntaxException;
41+
import java.net.URL;
42+
import java.util.List;
43+
44+
/**
45+
* @test
46+
* @bug 6563286 6797318 8177648
47+
* @summary Tests that sun.net.www.protocol.http.HttpURLConnection when dealing with
48+
* sun.net.spi.DefaultProxySelector#select() handles any IllegalArgumentException
49+
* correctly
50+
* @run testng HttpURLProxySelectionTest
51+
* @modules java.base/sun.net.spi:+open
52+
*/
53+
public class HttpURLProxySelectionTest {
54+
55+
private static final String WEB_APP_CONTEXT = "/httpurlproxytest";
56+
57+
private HttpServer server;
58+
private SimpleHandler handler;
59+
private ProxySelector previousDefault;
60+
private CustomProxySelector ourProxySelector = new CustomProxySelector();
61+
62+
@BeforeTest
63+
public void beforeTest() throws Exception {
64+
previousDefault = ProxySelector.getDefault();
65+
ProxySelector.setDefault(ourProxySelector);
66+
handler = new SimpleHandler();
67+
server = createServer(handler);
68+
}
69+
70+
@AfterTest
71+
public void afterTest() {
72+
try {
73+
if (server != null) {
74+
final int delaySeconds = 0;
75+
server.stop(delaySeconds);
76+
}
77+
} finally {
78+
ProxySelector.setDefault(previousDefault);
79+
}
80+
}
81+
82+
/**
83+
* - Test initiates a HTTP request to server
84+
* - Server receives request and sends a 301 redirect to an URI which doesn't have a "host"
85+
* - Redirect is expected to fail with IOException (caused by IllegalArgumentException from DefaultProxySelector)
86+
*
87+
* @throws Exception
88+
*/
89+
@Test
90+
public void test() throws Exception {
91+
final String targetURL = "http://" + server.getAddress().getHostName() + ":"
92+
+ server.getAddress().getPort() + WEB_APP_CONTEXT;
93+
System.out.println("Sending request to " + targetURL);
94+
final HttpURLConnection conn = (HttpURLConnection) new URL(targetURL).openConnection();
95+
try {
96+
conn.getResponseCode();
97+
Assert.fail("Request to " + targetURL + " was expected to fail during redirect");
98+
} catch (IOException ioe) {
99+
// expected because of the redirect to an invalid URL, for which a proxy can't be selected
100+
101+
// make sure the it was indeed a redirect
102+
Assert.assertTrue(handler.redirectSent, "Server was expected to send a redirect, but didn't");
103+
Assert.assertTrue(ourProxySelector.selectorUsedForRedirect, "Proxy selector wasn't used for redirect");
104+
105+
// make sure the IOException was caused by an IllegalArgumentException
106+
Assert.assertTrue(ioe.getCause() instanceof IllegalArgumentException, "Unexpected cause in the IOException");
107+
}
108+
}
109+
110+
111+
private static HttpServer createServer(final HttpHandler handler) throws IOException {
112+
final InetSocketAddress serverAddr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
113+
final int backlog = -1;
114+
final HttpServer server = HttpServer.create(serverAddr, backlog);
115+
// setup the handler
116+
server.createContext(WEB_APP_CONTEXT, handler);
117+
// start the server
118+
server.start();
119+
System.out.println("Server started on " + server.getAddress());
120+
return server;
121+
}
122+
123+
private static class SimpleHandler implements HttpHandler {
124+
private boolean redirectSent = false;
125+
126+
@Override
127+
public void handle(final HttpExchange httpExchange) throws IOException {
128+
final String redirectURL;
129+
try {
130+
redirectURL = new URI("http", "/irrelevant", null).toString();
131+
} catch (URISyntaxException e) {
132+
throw new IOException(e);
133+
}
134+
httpExchange.getResponseHeaders().add("Location", redirectURL);
135+
final URI requestURI = httpExchange.getRequestURI();
136+
System.out.println("Handling " + httpExchange.getRequestMethod() + " request "
137+
+ requestURI + " responding with redirect to " + redirectURL);
138+
httpExchange.sendResponseHeaders(301, -1);
139+
this.redirectSent = true;
140+
}
141+
142+
}
143+
144+
private static class CustomProxySelector extends DefaultProxySelector {
145+
146+
private boolean selectorUsedForRedirect = false;
147+
148+
@Override
149+
public List<Proxy> select(final URI uri) {
150+
if (uri.toString().contains("/irrelevant")) {
151+
this.selectorUsedForRedirect = true;
152+
}
153+
return super.select(uri);
154+
}
155+
}
156+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import org.testng.Assert;
25+
import org.testng.annotations.Test;
26+
import sun.net.spi.DefaultProxySelector;
27+
28+
import java.net.ProxySelector;
29+
import java.net.URI;
30+
31+
/**
32+
* @test
33+
* @bug 6563286 6797318 8177648
34+
* @summary Tests sun.net.spi.DefaultProxySelector#select(URI)
35+
* @run testng DefaultProxySelectorTest
36+
* @modules java.base/sun.net.spi:+open
37+
*/
38+
public class DefaultProxySelectorTest {
39+
40+
/**
41+
* Tests that {@link DefaultProxySelector#select(URI)} throws
42+
* {@link IllegalArgumentException} when passed {@code null}
43+
*/
44+
@Test
45+
public void testIllegalArgForNull() {
46+
final ProxySelector selector = new DefaultProxySelector();
47+
try {
48+
selector.select(null);
49+
Assert.fail("select() was expected to fail for null URI");
50+
} catch (IllegalArgumentException iae) {
51+
// expected
52+
}
53+
}
54+
55+
/**
56+
* Tests that {@link DefaultProxySelector} throws a {@link IllegalArgumentException}
57+
* for URIs that don't have host information
58+
*
59+
* @throws Exception
60+
*/
61+
@Test
62+
public void testIllegalArgForNoHost() throws Exception {
63+
final ProxySelector selector = new DefaultProxySelector();
64+
assertFailsWithIAE(selector, new URI("http", "/test", null));
65+
assertFailsWithIAE(selector, new URI("https", "/test2", null));
66+
assertFailsWithIAE(selector, new URI("ftp", "/test3", null));
67+
}
68+
69+
70+
/**
71+
* Tests that {@link DefaultProxySelector} throws a {@link IllegalArgumentException}
72+
* for URIs that don't have protocol/scheme information
73+
*
74+
* @throws Exception
75+
*/
76+
@Test
77+
public void testIllegalArgForNoScheme() throws Exception {
78+
final ProxySelector selector = new DefaultProxySelector();
79+
assertFailsWithIAE(selector, new URI(null, "/test", null));
80+
}
81+
82+
private static void assertFailsWithIAE(final ProxySelector selector, final URI uri) {
83+
try {
84+
selector.select(uri);
85+
Assert.fail("select() was expected to fail for URI " + uri);
86+
} catch (IllegalArgumentException iae) {
87+
// expected
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)