22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 8156514 |
26 * @bug 8156514 |
27 * @key intermittent |
|
28 * @library /lib/testlibrary server |
27 * @library /lib/testlibrary server |
29 * @build jdk.testlibrary.SimpleSSLContext |
28 * @build jdk.testlibrary.SimpleSSLContext |
30 * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.common |
29 * @modules java.base/sun.net.www.http |
31 * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.frame |
30 * jdk.incubator.httpclient/jdk.incubator.http.internal.common |
32 * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.hpack |
31 * jdk.incubator.httpclient/jdk.incubator.http.internal.frame |
|
32 * jdk.incubator.httpclient/jdk.incubator.http.internal.hpack |
33 * @run testng/othervm -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors RedirectTest |
33 * @run testng/othervm -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors RedirectTest |
34 */ |
34 */ |
35 |
35 |
36 import java.net.*; |
36 import java.net.*; |
37 import jdk.incubator.http.*; |
37 import jdk.incubator.http.*; |
38 import static jdk.incubator.http.HttpClient.Version.HTTP_2; |
38 import java.util.Optional; |
39 import java.nio.file.*; |
|
40 import java.util.concurrent.*; |
39 import java.util.concurrent.*; |
41 import java.util.function.*; |
40 import java.util.function.*; |
42 import java.util.Arrays; |
41 import java.util.Arrays; |
43 import java.util.Iterator; |
42 import java.util.Iterator; |
44 import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString; |
43 import org.testng.annotations.Test; |
|
44 import static jdk.incubator.http.HttpClient.Version.HTTP_2; |
|
45 import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString; |
45 import static jdk.incubator.http.HttpResponse.BodyHandler.asString; |
46 import static jdk.incubator.http.HttpResponse.BodyHandler.asString; |
46 |
47 |
47 import org.testng.annotations.Test; |
|
48 |
|
49 @Test |
|
50 public class RedirectTest { |
48 public class RedirectTest { |
51 static int httpPort, altPort; |
49 static int httpPort; |
52 static Http2TestServer httpServer, altServer; |
50 static Http2TestServer httpServer; |
53 static HttpClient client; |
51 static HttpClient client; |
54 static ExecutorService exec; |
|
55 |
52 |
56 static String httpURIString, altURIString1, altURIString2; |
53 static String httpURIString, altURIString1, altURIString2; |
|
54 static URI httpURI, altURI1, altURI2; |
57 |
55 |
58 static Supplier<String> sup(String... args) { |
56 static Supplier<String> sup(String... args) { |
59 Iterator<String> i = Arrays.asList(args).iterator(); |
57 Iterator<String> i = Arrays.asList(args).iterator(); |
60 // need to know when to stop calling it. |
58 // need to know when to stop calling it. |
61 return () -> i.next(); |
59 return () -> i.next(); |
62 } |
60 } |
63 |
61 |
|
62 static class Redirector extends Http2RedirectHandler { |
|
63 private InetSocketAddress remoteAddr; |
|
64 private boolean error = false; |
|
65 |
|
66 Redirector(Supplier<String> supplier) { |
|
67 super(supplier); |
|
68 } |
|
69 |
|
70 protected synchronized void examineExchange(Http2TestExchange ex) { |
|
71 InetSocketAddress addr = ex.getRemoteAddress(); |
|
72 if (remoteAddr == null) { |
|
73 remoteAddr = addr; |
|
74 return; |
|
75 } |
|
76 // check that the client addr/port stays the same, proving |
|
77 // that the connection didn't get dropped. |
|
78 if (!remoteAddr.equals(addr)) { |
|
79 System.err.printf("Error %s/%s\n", remoteAddr.toString(), |
|
80 addr.toString()); |
|
81 error = true; |
|
82 } |
|
83 } |
|
84 |
|
85 public synchronized boolean error() { |
|
86 return error; |
|
87 } |
|
88 } |
|
89 |
64 static void initialize() throws Exception { |
90 static void initialize() throws Exception { |
65 try { |
91 try { |
66 client = getClient(); |
92 client = getClient(); |
67 httpServer = new Http2TestServer(false, 0, exec, null); |
93 httpServer = new Http2TestServer(false, 0, null, null); |
68 |
|
69 httpPort = httpServer.getAddress().getPort(); |
94 httpPort = httpServer.getAddress().getPort(); |
70 altServer = new Http2TestServer(false, 0, exec, null); |
95 |
71 altPort = altServer.getAddress().getPort(); |
96 // urls are accessed in sequence below. The first two are on |
72 |
97 // different servers. Third on same server as second. So, the |
73 // urls are accessed in sequence below |
98 // client should use the same http connection. |
74 // first two on different servers. Third on same server |
|
75 // as second. So, the client should use the same http connection |
|
76 httpURIString = "http://127.0.0.1:" + httpPort + "/foo/"; |
99 httpURIString = "http://127.0.0.1:" + httpPort + "/foo/"; |
77 altURIString1 = "http://127.0.0.1:" + altPort + "/redir"; |
100 httpURI = URI.create(httpURIString); |
78 altURIString2 = "http://127.0.0.1:" + altPort + "/redir/again"; |
101 altURIString1 = "http://127.0.0.1:" + httpPort + "/redir"; |
79 |
102 altURI1 = URI.create(altURIString1); |
80 httpServer.addHandler(new RedirectHandler(sup(altURIString1)), "/foo"); |
103 altURIString2 = "http://127.0.0.1:" + httpPort + "/redir_again"; |
81 altServer.addHandler(new RedirectHandler(sup(altURIString2)), "/redir"); |
104 altURI2 = URI.create(altURIString2); |
82 altServer.addHandler(new Http2EchoHandler(), "/redir/again"); |
105 |
|
106 Redirector r = new Redirector(sup(altURIString1, altURIString2)); |
|
107 httpServer.addHandler(r, "/foo"); |
|
108 httpServer.addHandler(r, "/redir"); |
|
109 httpServer.addHandler(new Http2EchoHandler(), "/redir_again"); |
83 |
110 |
84 httpServer.start(); |
111 httpServer.start(); |
85 altServer.start(); |
|
86 } catch (Throwable e) { |
112 } catch (Throwable e) { |
87 System.err.println("Throwing now"); |
113 System.err.println("Throwing now"); |
88 e.printStackTrace(); |
114 e.printStackTrace(); |
89 throw e; |
115 throw e; |
90 } |
116 } |
91 } |
117 } |
92 |
118 |
93 @Test(timeOut=3000000) |
119 @Test |
94 public static void test() throws Exception { |
120 public static void test() throws Exception { |
95 try { |
121 try { |
96 initialize(); |
122 initialize(); |
97 simpleTest(); |
123 simpleTest(); |
98 } catch (Throwable tt) { |
|
99 System.err.println("tt caught"); |
|
100 tt.printStackTrace(); |
|
101 } finally { |
124 } finally { |
102 httpServer.stop(); |
125 httpServer.stop(); |
103 altServer.stop(); |
|
104 exec.shutdownNow(); |
|
105 } |
126 } |
106 } |
127 } |
107 |
128 |
108 static HttpClient getClient() { |
129 static HttpClient getClient() { |
109 if (client == null) { |
130 if (client == null) { |
110 exec = Executors.newCachedThreadPool(); |
|
111 client = HttpClient.newBuilder() |
131 client = HttpClient.newBuilder() |
112 .executor(exec) |
|
113 .followRedirects(HttpClient.Redirect.ALWAYS) |
132 .followRedirects(HttpClient.Redirect.ALWAYS) |
114 .version(HTTP_2) |
133 .version(HTTP_2) |
115 .build(); |
134 .build(); |
116 } |
135 } |
117 return client; |
136 return client; |
127 expected, found); |
146 expected, found); |
128 throw new RuntimeException("Test failed"); |
147 throw new RuntimeException("Test failed"); |
129 } |
148 } |
130 } |
149 } |
131 |
150 |
|
151 static void checkURIs(URI expected, URI found) throws Exception { |
|
152 System.out.printf ("Expected: %s, Found: %s\n", expected.toString(), found.toString()); |
|
153 if (!expected.equals(found)) { |
|
154 System.err.printf ("Test failed: wrong URI %s/%s\n", |
|
155 expected.toString(), found.toString()); |
|
156 throw new RuntimeException("Test failed"); |
|
157 } |
|
158 } |
|
159 |
132 static void checkStrings(String expected, String found) throws Exception { |
160 static void checkStrings(String expected, String found) throws Exception { |
133 if (!expected.equals(found)) { |
161 if (!expected.equals(found)) { |
134 System.err.printf ("Test failed: wrong string %s/%s\n", |
162 System.err.printf ("Test failed: wrong string %s/%s\n", |
135 expected, found); |
163 expected, found); |
136 throw new RuntimeException("Test failed"); |
164 throw new RuntimeException("Test failed"); |
137 } |
165 } |
138 } |
166 } |
139 |
167 |
140 static Void compareFiles(Path path1, Path path2) { |
168 static void check(boolean cond, Object... msg) { |
141 return TestUtil.compareFiles(path1, path2); |
169 if (cond) |
142 } |
170 return; |
143 |
171 StringBuilder sb = new StringBuilder(); |
144 static Path tempFile() { |
172 for (Object o : msg) |
145 return TestUtil.tempFile(); |
173 sb.append(o); |
|
174 throw new RuntimeException(sb.toString()); |
146 } |
175 } |
147 |
176 |
148 static final String SIMPLE_STRING = "Hello world Goodbye world"; |
177 static final String SIMPLE_STRING = "Hello world Goodbye world"; |
149 |
|
150 static final int FILESIZE = 64 * 1024 + 200; |
|
151 |
178 |
152 static void simpleTest() throws Exception { |
179 static void simpleTest() throws Exception { |
153 URI uri = getURI(); |
180 URI uri = getURI(); |
154 System.err.println("Request to " + uri); |
181 System.err.println("Request to " + uri); |
155 |
182 |
161 HttpResponse<String> response = cf.join(); |
188 HttpResponse<String> response = cf.join(); |
162 |
189 |
163 checkStatus(200, response.statusCode()); |
190 checkStatus(200, response.statusCode()); |
164 String responseBody = response.body(); |
191 String responseBody = response.body(); |
165 checkStrings(SIMPLE_STRING, responseBody); |
192 checkStrings(SIMPLE_STRING, responseBody); |
|
193 checkURIs(response.uri(), altURI2); |
|
194 |
|
195 // check two previous responses |
|
196 HttpResponse<String> prev = response.previousResponse() |
|
197 .orElseThrow(() -> new RuntimeException("no previous response")); |
|
198 checkURIs(prev.uri(), altURI1); |
|
199 |
|
200 prev = prev.previousResponse() |
|
201 .orElseThrow(() -> new RuntimeException("no previous response")); |
|
202 checkURIs(prev.uri(), httpURI); |
|
203 |
|
204 checkPreviousRedirectResponses(req, response); |
166 |
205 |
167 System.err.println("DONE"); |
206 System.err.println("DONE"); |
168 Thread.sleep (6000); |
207 } |
|
208 |
|
209 static void checkPreviousRedirectResponses(HttpRequest initialRequest, |
|
210 HttpResponse<?> finalResponse) { |
|
211 // there must be at least one previous response |
|
212 finalResponse.previousResponse() |
|
213 .orElseThrow(() -> new RuntimeException("no previous response")); |
|
214 |
|
215 HttpResponse<?> response = finalResponse; |
|
216 do { |
|
217 URI uri = response.uri(); |
|
218 response = response.previousResponse().get(); |
|
219 check(300 <= response.statusCode() && response.statusCode() <= 309, |
|
220 "Expected 300 <= code <= 309, got:" + response.statusCode()); |
|
221 check(response.body() == null, "Unexpected body: " + response.body()); |
|
222 String locationHeader = response.headers().firstValue("Location") |
|
223 .orElseThrow(() -> new RuntimeException("no previous Location")); |
|
224 check(uri.toString().endsWith(locationHeader), |
|
225 "URI: " + uri + ", Location: " + locationHeader); |
|
226 } while (response.previousResponse().isPresent()); |
|
227 |
|
228 // initial |
|
229 check(initialRequest.equals(response.request()), |
|
230 "Expected initial request [%s] to equal last prev req [%s]", |
|
231 initialRequest, response.request()); |
169 } |
232 } |
170 } |
233 } |