37 import java.net.*; |
37 import java.net.*; |
38 import java.nio.ByteBuffer; |
38 import java.nio.ByteBuffer; |
39 import java.nio.file.*; |
39 import java.nio.file.*; |
40 import jdk.incubator.http.*; |
40 import jdk.incubator.http.*; |
41 import jdk.incubator.http.HttpResponse.BodyHandler; |
41 import jdk.incubator.http.HttpResponse.BodyHandler; |
|
42 import jdk.incubator.http.HttpResponse.BodySubscriber; |
42 import jdk.incubator.http.HttpResponse.PushPromiseHandler; |
43 import jdk.incubator.http.HttpResponse.PushPromiseHandler; |
43 import java.util.*; |
44 import java.util.*; |
44 import java.util.concurrent.*; |
45 import java.util.concurrent.*; |
45 import java.util.function.Consumer; |
46 import java.util.function.Consumer; |
46 import java.util.function.UnaryOperator; |
47 import java.util.function.UnaryOperator; |
47 |
|
48 import org.testng.annotations.AfterTest; |
48 import org.testng.annotations.AfterTest; |
49 import org.testng.annotations.BeforeTest; |
49 import org.testng.annotations.BeforeTest; |
50 import org.testng.annotations.Test; |
50 import org.testng.annotations.Test; |
51 import static java.nio.charset.StandardCharsets.UTF_8; |
51 import static java.nio.charset.StandardCharsets.UTF_8; |
|
52 import static jdk.incubator.http.HttpResponse.BodyHandler.asByteArrayConsumer; |
|
53 import static jdk.incubator.http.HttpResponse.BodyHandler.asFile; |
|
54 import static jdk.incubator.http.HttpResponse.BodyHandler.asString; |
52 import static org.testng.Assert.*; |
55 import static org.testng.Assert.*; |
53 |
56 |
54 |
57 |
55 public class ServerPush { |
58 public class ServerPush { |
56 |
59 |
78 @AfterTest |
81 @AfterTest |
79 public void teardown() { |
82 public void teardown() { |
80 server.stop(); |
83 server.stop(); |
81 } |
84 } |
82 |
85 |
83 static final UnaryOperator<HttpResponse<?>> |
86 // Test 1 - custom written push promise handler, everything as a String |
84 assert200ResponseCode = (response) -> { |
|
85 assertEquals(response.statusCode(), 200); |
|
86 return response; |
|
87 }; |
|
88 |
|
89 interface Peeker<T> extends UnaryOperator<T> { |
|
90 void peek(T t); |
|
91 |
|
92 default T apply(T t) |
|
93 { |
|
94 peek(t); |
|
95 return t; |
|
96 } |
|
97 } |
|
98 |
|
99 @Test |
87 @Test |
100 public void testTypeString() throws Exception { |
88 public void testTypeString() throws Exception { |
101 // use multi-level path |
89 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
102 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
90 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>> |
103 |
91 resultMap = new ConcurrentHashMap<>(); |
104 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
92 |
105 |
|
106 // Attempt 2 |
|
107 HttpClient client = HttpClient.newBuilder() |
|
108 .version(HttpClient.Version.HTTP_2) |
|
109 .build(); |
|
110 |
|
111 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>> results = new ConcurrentHashMap<>(); |
|
112 |
|
113 |
|
114 // Example 2 - of(...) building your own Map, everything as a String |
|
115 PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> { |
93 PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> { |
116 BodyHandler<String> s = BodyHandler.asString(UTF_8); |
94 BodyHandler<String> s = BodyHandler.asString(UTF_8); |
117 CompletableFuture<HttpResponse<String>> cf = acceptor.apply(s); |
95 CompletableFuture<HttpResponse<String>> cf = acceptor.apply(s); |
118 results.put(pushRequest, cf); |
96 resultMap.put(pushRequest, cf); |
119 }; |
97 }; |
120 |
98 |
|
99 HttpClient client = HttpClient.newHttpClient(); |
|
100 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
121 CompletableFuture<HttpResponse<String>> cf = |
101 CompletableFuture<HttpResponse<String>> cf = |
122 client.sendAsync(request, BodyHandler.asString(), pph); |
102 client.sendAsync(request, asString(UTF_8), pph); |
123 cf.join(); |
103 cf.join(); |
124 results.put(request, cf); |
104 resultMap.put(request, cf); |
125 |
105 System.err.println("results.size: " + resultMap.size()); |
126 System.err.println(results.size()); |
106 for (HttpRequest r : resultMap.keySet()) { |
127 Set<HttpRequest> requests = results.keySet(); |
107 HttpResponse<String> response = resultMap.get(r).join(); |
128 |
108 assertEquals(response.statusCode(), 200); |
129 System.err.println("results.size: " + results.size()); |
109 assertEquals(response.body(), tempFileAsString); |
130 for (HttpRequest r : requests) { |
110 } |
131 String result = results.get(r).get().body(); |
111 assertEquals(resultMap.size(), LOOPS + 1); |
132 if (!result.equals(tempFileAsString)) { |
112 } |
133 System.err.println("Got [" + result + ", expected [" + tempFileAsString + "]"); |
113 |
134 } |
114 // Test 2 - of(...) populating the given Map, everything as a String |
135 } |
115 @Test |
136 if (requests.size() != LOOPS + 1) |
116 public void testTypeStringOfMap() throws Exception { |
137 throw new RuntimeException("Some results missing, expected:" + LOOPS + 1 + ", got:" + results.size()); |
117 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
|
118 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>> |
|
119 resultMap = new ConcurrentHashMap<>(); |
|
120 |
|
121 PushPromiseHandler<String> pph = |
|
122 PushPromiseHandler.of(pushPromise -> asString(UTF_8), |
|
123 resultMap); |
|
124 |
|
125 HttpClient client = HttpClient.newHttpClient(); |
|
126 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
|
127 CompletableFuture<HttpResponse<String>> cf = |
|
128 client.sendAsync(request, asString(UTF_8), pph); |
|
129 cf.join(); |
|
130 resultMap.put(request, cf); |
|
131 System.err.println("results.size: " + resultMap.size()); |
|
132 for (HttpRequest r : resultMap.keySet()) { |
|
133 HttpResponse<String> response = resultMap.get(r).join(); |
|
134 assertEquals(response.statusCode(), 200); |
|
135 assertEquals(response.body(), tempFileAsString); |
|
136 } |
|
137 assertEquals(resultMap.size(), LOOPS + 1); |
138 } |
138 } |
139 |
139 |
140 // --- Path --- |
140 // --- Path --- |
141 |
141 |
142 static final Path dir = Paths.get(".", "serverPush"); |
142 static final Path dir = Paths.get(".", "serverPush"); |
146 try { |
146 try { |
147 Files.createDirectories(path.getParent()); |
147 Files.createDirectories(path.getParent()); |
148 } catch (IOException ee) { |
148 } catch (IOException ee) { |
149 throw new UncheckedIOException(ee); |
149 throw new UncheckedIOException(ee); |
150 } |
150 } |
151 return BodyHandler.asFile(path); |
151 return asFile(path); |
152 }; |
152 } |
153 |
153 |
|
154 // Test 3 - custom written push promise handler, everything as a Path |
154 @Test |
155 @Test |
155 public void testTypePath() throws Exception { |
156 public void testTypePath() throws Exception { |
156 HttpClient client = HttpClient.newHttpClient(); |
157 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
157 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
158 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap |
158 |
159 = new ConcurrentHashMap<>(); |
159 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> map |
160 |
160 = new ConcurrentHashMap<>(); |
|
161 |
|
162 // Example 4 - of(...) building your own Map, everything as a Path |
|
163 PushPromiseHandler<Path> pushPromiseHandler = (initial, pushRequest, acceptor) -> { |
161 PushPromiseHandler<Path> pushPromiseHandler = (initial, pushRequest, acceptor) -> { |
164 BodyHandler<Path> pp = requestToPath(pushRequest); |
162 BodyHandler<Path> pp = requestToPath(pushRequest); |
165 CompletableFuture<HttpResponse<Path>> cf = acceptor.apply(pp); |
163 CompletableFuture<HttpResponse<Path>> cf = acceptor.apply(pp); |
166 map.put(pushRequest, cf); |
164 resultsMap.put(pushRequest, cf); |
167 }; |
165 }; |
168 |
166 |
|
167 HttpClient client = HttpClient.newHttpClient(); |
|
168 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
169 CompletableFuture<HttpResponse<Path>> cf = |
169 CompletableFuture<HttpResponse<Path>> cf = |
170 client.sendAsync(request, requestToPath(request), pushPromiseHandler); |
170 client.sendAsync(request, requestToPath(request), pushPromiseHandler); |
171 cf.join(); |
171 cf.join(); |
172 map.put(request, cf); |
172 resultsMap.put(request, cf); |
173 |
173 |
174 System.err.println("map.size: " + map.size()); |
174 for (HttpRequest r : resultsMap.keySet()) { |
175 for (HttpRequest r : map.keySet()) { |
175 HttpResponse<Path> response = resultsMap.get(r).join(); |
176 Path path = map.get(r).get().body(); |
176 assertEquals(response.statusCode(), 200); |
177 String fileAsString = new String(Files.readAllBytes(path), UTF_8); |
177 String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8); |
178 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
|
179 assertEquals(fileAsString, tempFileAsString); |
178 assertEquals(fileAsString, tempFileAsString); |
180 } |
179 } |
181 assertEquals(map.size(), LOOPS + 1); |
180 assertEquals(resultsMap.size(), LOOPS + 1); |
|
181 } |
|
182 |
|
183 // Test 4 - of(...) populating the given Map, everything as a Path |
|
184 @Test |
|
185 public void testTypePathOfMap() throws Exception { |
|
186 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
|
187 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap |
|
188 = new ConcurrentHashMap<>(); |
|
189 |
|
190 PushPromiseHandler<Path> pushPromiseHandler = |
|
191 PushPromiseHandler.of(pushRequest -> requestToPath(pushRequest), |
|
192 resultsMap); |
|
193 |
|
194 HttpClient client = HttpClient.newHttpClient(); |
|
195 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
|
196 CompletableFuture<HttpResponse<Path>> cf = |
|
197 client.sendAsync(request, requestToPath(request), pushPromiseHandler); |
|
198 cf.join(); |
|
199 resultsMap.put(request, cf); |
|
200 |
|
201 for (HttpRequest r : resultsMap.keySet()) { |
|
202 HttpResponse<Path> response = resultsMap.get(r).join(); |
|
203 assertEquals(response.statusCode(), 200); |
|
204 String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8); |
|
205 assertEquals(fileAsString, tempFileAsString); |
|
206 } |
|
207 assertEquals(resultsMap.size(), LOOPS + 1); |
182 } |
208 } |
183 |
209 |
184 // --- Consumer<byte[]> --- |
210 // --- Consumer<byte[]> --- |
185 |
211 |
186 static class ByteArrayConsumer implements Consumer<Optional<byte[]>> { |
212 static class ByteArrayConsumer implements Consumer<Optional<byte[]>> { |
201 listByteArrays.add(optionalBytes.get()); |
227 listByteArrays.add(optionalBytes.get()); |
202 } |
228 } |
203 } |
229 } |
204 } |
230 } |
205 |
231 |
|
232 // Test 5 - custom written handler, everything as a consumer of optional byte[] |
206 @Test |
233 @Test |
207 public void testTypeByteArrayConsumer() throws Exception { |
234 public void testTypeByteArrayConsumer() throws Exception { |
208 HttpClient client = HttpClient.newHttpClient(); |
235 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
209 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
236 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap |
210 |
|
211 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultMap |
|
212 = new ConcurrentHashMap<>(); |
237 = new ConcurrentHashMap<>(); |
213 Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap |
238 Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap |
214 = new ConcurrentHashMap<>(); |
239 = new ConcurrentHashMap<>(); |
215 |
240 |
|
241 HttpClient client = HttpClient.newHttpClient(); |
|
242 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
216 ByteArrayConsumer bac = new ByteArrayConsumer(); |
243 ByteArrayConsumer bac = new ByteArrayConsumer(); |
217 byteArrayConsumerMap.put(request, bac); |
244 byteArrayConsumerMap.put(request, bac); |
218 |
245 |
219 // Example 5 - withXXX and everything as a consumer of optional byte[] |
246 PushPromiseHandler<Void> pushPromiseHandler = (initial, pushRequest, acceptor) -> { |
220 PushPromiseHandler<Void> pushPromiseHandler = |
247 CompletableFuture<HttpResponse<Void>> cf = acceptor.apply( |
221 PushPromiseHandler.of(pushRequest -> { |
248 (statusCode, headers) -> { |
222 ByteArrayConsumer bc = new ByteArrayConsumer(); |
249 ByteArrayConsumer bc = new ByteArrayConsumer(); |
223 byteArrayConsumerMap.put(pushRequest, bc); |
250 byteArrayConsumerMap.put(pushRequest, bc); |
224 return BodyHandler.asByteArrayConsumer(bc); |
251 return BodySubscriber.asByteArrayConsumer(bc); } ); |
225 }, |
252 resultsMap.put(pushRequest, cf); |
226 resultMap); |
253 }; |
227 |
254 |
228 CompletableFuture<HttpResponse<Void>> cf = |
255 CompletableFuture<HttpResponse<Void>> cf = |
229 client.sendAsync(request, BodyHandler.asByteArrayConsumer(bac), pushPromiseHandler); |
256 client.sendAsync(request, asByteArrayConsumer(bac), pushPromiseHandler); |
230 cf.join(); |
257 cf.join(); |
231 resultMap.put(request, cf); |
258 resultsMap.put(request, cf); |
232 |
259 |
233 System.err.println("map.size: " + resultMap.size()); |
260 for (HttpRequest r : resultsMap.keySet()) { |
234 for (HttpRequest r : resultMap.keySet()) { |
261 HttpResponse<Void> response = resultsMap.get(r).join(); |
235 resultMap.get(r).join(); |
262 assertEquals(response.statusCode(), 200); |
236 byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); |
263 byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); |
237 String result = new String(ba, UTF_8); |
264 String result = new String(ba, UTF_8); |
238 System.out.println("HEGO result=" + result); |
|
239 System.out.println("HEGO result.length=" + result.length()); |
|
240 System.err.printf("%s -> %s\n", r.uri().toString(), result); |
|
241 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
|
242 System.out.println("HEGO tempFileAsString=" + tempFileAsString); |
|
243 System.out.println("HEGO tempFileAsString.length=" + tempFileAsString.length()); |
|
244 assertEquals(result, tempFileAsString); |
265 assertEquals(result, tempFileAsString); |
245 } |
266 } |
246 |
267 assertEquals(resultsMap.size(), LOOPS + 1); |
247 assertEquals(resultMap.size(), LOOPS + 1); |
268 } |
|
269 |
|
270 // Test 6 - of(...) populating the given Map, everything as a consumer of optional byte[] |
|
271 @Test |
|
272 public void testTypeByteArrayConsumerOfMap() throws Exception { |
|
273 String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8); |
|
274 ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap |
|
275 = new ConcurrentHashMap<>(); |
|
276 Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap |
|
277 = new ConcurrentHashMap<>(); |
|
278 |
|
279 HttpClient client = HttpClient.newHttpClient(); |
|
280 HttpRequest request = HttpRequest.newBuilder(uri).GET().build(); |
|
281 ByteArrayConsumer bac = new ByteArrayConsumer(); |
|
282 byteArrayConsumerMap.put(request, bac); |
|
283 |
|
284 PushPromiseHandler<Void> pushPromiseHandler = |
|
285 PushPromiseHandler.of( |
|
286 pushRequest -> { |
|
287 ByteArrayConsumer bc = new ByteArrayConsumer(); |
|
288 byteArrayConsumerMap.put(pushRequest, bc); |
|
289 return BodyHandler.asByteArrayConsumer(bc); |
|
290 }, |
|
291 resultsMap); |
|
292 |
|
293 CompletableFuture<HttpResponse<Void>> cf = |
|
294 client.sendAsync(request, asByteArrayConsumer(bac), pushPromiseHandler); |
|
295 cf.join(); |
|
296 resultsMap.put(request, cf); |
|
297 |
|
298 for (HttpRequest r : resultsMap.keySet()) { |
|
299 HttpResponse<Void> response = resultsMap.get(r).join(); |
|
300 assertEquals(response.statusCode(), 200); |
|
301 byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); |
|
302 String result = new String(ba, UTF_8); |
|
303 assertEquals(result, tempFileAsString); |
|
304 } |
|
305 assertEquals(resultsMap.size(), LOOPS + 1); |
248 } |
306 } |
249 } |
307 } |