< prev index next >

test/jdk/java/net/httpclient/ResponsePublisher.java

Print this page

 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 /*
 25  * @test
 26  * @bug 8201186
 27  * @summary Tests an asynchronous BodySubscriber that completes
 28  *          immediately with a Publisher<List<ByteBuffer>>
 29  * @library /test/lib /test/jdk/java/net/httpclient/lib
 30  * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters
 31  * @run testng/othervm ResponsePublisher
 32  */
 33 
 34 import com.sun.net.httpserver.HttpExchange;
 35 import com.sun.net.httpserver.HttpHandler;
 36 import com.sun.net.httpserver.HttpServer;
 37 import com.sun.net.httpserver.HttpsConfigurator;
 38 import com.sun.net.httpserver.HttpsServer;

 39 import jdk.test.lib.net.SimpleSSLContext;
 40 import org.testng.annotations.AfterTest;
 41 import org.testng.annotations.BeforeTest;
 42 import org.testng.annotations.DataProvider;
 43 import org.testng.annotations.Test;
 44 
 45 import javax.net.ssl.SSLContext;
 46 import java.io.IOException;
 47 import java.io.InputStream;
 48 import java.io.OutputStream;
 49 import java.net.InetAddress;
 50 import java.net.InetSocketAddress;
 51 import java.net.URI;
 52 import java.net.http.HttpClient;
 53 import java.net.http.HttpHeaders;
 54 import java.net.http.HttpRequest;
 55 import java.net.http.HttpResponse;
 56 import java.net.http.HttpResponse.BodyHandler;
 57 import java.net.http.HttpResponse.BodyHandlers;
 58 import java.net.http.HttpResponse.BodySubscriber;

 83 public class ResponsePublisher implements HttpServerAdapters {
 84 
 85     SSLContext sslContext;
 86     HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
 87     HttpTestServer httpsTestServer;   // HTTPS/1.1
 88     HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
 89     HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
 90     String httpURI_fixed;
 91     String httpURI_chunk;
 92     String httpsURI_fixed;
 93     String httpsURI_chunk;
 94     String http2URI_fixed;
 95     String http2URI_chunk;
 96     String https2URI_fixed;
 97     String https2URI_chunk;
 98 
 99     static final int ITERATION_COUNT = 3;
100     // a shared executor helps reduce the amount of threads created by the test
101     static final Executor executor = Executors.newCachedThreadPool();
102 










103     interface BHS extends Supplier<BodyHandler<Publisher<List<ByteBuffer>>>> {
104         static BHS of(BHS impl, String name) {
105             return new BHSImpl(impl, name);
106         }
107     }
108 
109     static final class BHSImpl implements BHS {
110         final BHS supplier;
111         final String name;
112         BHSImpl(BHS impl, String name) {
113             this.supplier = impl;
114             this.name = name;
115         }
116         @Override
117         public String toString() {
118             return name;
119         }
120 
121         @Override
122         public BodyHandler<Publisher<List<ByteBuffer>>> get() {

199             // Publisher<List<ByteBuffer>>
200             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
201             response.body().subscribe(ofString);
202 
203             BodySubscriber<String> ofString2 = BodySubscribers.ofString(UTF_8);
204             response.body().subscribe(ofString2);
205             try {
206                 ofString2.getBody().toCompletableFuture().join();
207                 throw new RuntimeException("Expected ISE not thrown");
208             } catch (CompletionException x) {
209                 Throwable cause = x.getCause();
210                 if (cause instanceof  IllegalStateException) {
211                     System.out.println("Got expected ISE: " + cause);
212                 } else {
213                     throw x;
214                 }
215             }
216             // Get the final result and compare it with the expected body
217             String body = ofString.getBody().toCompletableFuture().get();
218             assertEquals(body, "");






219         }
220     }
221 
222     @Test(dataProvider = "variants")
223     public void testNoBody(String uri, boolean sameClient, BHS handlers) throws Exception {
224         HttpClient client = null;
225         for (int i=0; i< ITERATION_COUNT; i++) {
226             if (!sameClient || client == null)
227                 client = newHttpClient();
228 
229             HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
230                     .build();
231             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
232             HttpResponse<Publisher<List<ByteBuffer>>> response = client.send(req, handler);
233             // We can reuse our BodySubscribers implementations to subscribe to the
234             // Publisher<List<ByteBuffer>>
235             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
236             // get the Publisher<List<ByteBuffer>> and
237             // subscribe to it.
238             response.body().subscribe(ofString);
239             // Get the final result and compare it with the expected body
240             String body = ofString.getBody().toCompletableFuture().get();
241             assertEquals(body, "");






242         }
243     }
244 
245     @Test(dataProvider = "variants")
246     public void testNoBodyAsync(String uri, boolean sameClient, BHS handlers) throws Exception {
247         HttpClient client = null;
248         for (int i=0; i< ITERATION_COUNT; i++) {
249             if (!sameClient || client == null)
250                 client = newHttpClient();
251 
252             HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
253                     .build();
254             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
255             // We can reuse our BodySubscribers implementations to subscribe to the
256             // Publisher<List<ByteBuffer>>
257             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
258             CompletableFuture<String> result =
259                     client.sendAsync(req, handler).thenCompose(
260                             (responsePublisher) -> {
261                                 // get the Publisher<List<ByteBuffer>> and
262                                 // subscribe to it.
263                                 responsePublisher.body().subscribe(ofString);
264                                 return ofString.getBody();
265                             });
266             // Get the final result and compare it with the expected body
267             assertEquals(result.get(), "");






268         }
269     }
270 
271     @Test(dataProvider = "variants")
272     public void testAsString(String uri, boolean sameClient, BHS handlers) throws Exception {
273         HttpClient client = null;
274         for (int i=0; i< ITERATION_COUNT; i++) {
275             if (!sameClient || client == null)
276                 client = newHttpClient();
277 
278             HttpRequest req = HttpRequest.newBuilder(URI.create(uri+"/withBody"))
279                     .build();
280             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
281             HttpResponse<Publisher<List<ByteBuffer>>> response = client.send(req, handler);
282             // We can reuse our BodySubscribers implementations to subscribe to the
283             // Publisher<List<ByteBuffer>>
284             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
285             // get the Publisher<List<ByteBuffer>> and
286             // subscribe to it.
287             response.body().subscribe(ofString);
288             // Get the final result and compare it with the expected body
289             String body = ofString.getBody().toCompletableFuture().get();
290             assertEquals(body, WITH_BODY);






291         }
292     }
293 
294     @Test(dataProvider = "variants")
295     public void testAsStringAsync(String uri, boolean sameClient, BHS handlers) throws Exception {
296         HttpClient client = null;
297         for (int i=0; i< ITERATION_COUNT; i++) {
298             if (!sameClient || client == null)
299                 client = newHttpClient();
300 
301             HttpRequest req = HttpRequest.newBuilder(URI.create(uri+"/withBody"))
302                     .build();
303             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
304             // We can reuse our BodySubscribers implementations to subscribe to the
305             // Publisher<List<ByteBuffer>>
306             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
307             CompletableFuture<String> result = client.sendAsync(req, handler)
308                     .thenCompose((responsePublisher) -> {
309                         // get the Publisher<List<ByteBuffer>> and
310                         // subscribe to it.
311                         responsePublisher.body().subscribe(ofString);
312                         return ofString.getBody();
313                     });
314             // Get the final result and compare it with the expected body
315             String body = result.get();
316             assertEquals(body, WITH_BODY);






317         }
318     }
319 
320     // A BodyHandler that returns PublishingBodySubscriber instances
321     static class PublishingBodyHandler implements BodyHandler<Publisher<List<ByteBuffer>>> {
322         @Override
323         public BodySubscriber<Publisher<List<ByteBuffer>>> apply(HttpResponse.ResponseInfo rinfo) {
324             assertEquals(rinfo.statusCode(), 200);
325             return new PublishingBodySubscriber();
326         }
327     }
328 
329     // A BodySubscriber that returns a Publisher<List<ByteBuffer>>
330     static class PublishingBodySubscriber implements BodySubscriber<Publisher<List<ByteBuffer>>> {
331         private final CompletableFuture<Flow.Subscription> subscriptionCF = new CompletableFuture<>();
332         private final CompletableFuture<Flow.Subscriber<? super List<ByteBuffer>>> subscribedCF = new CompletableFuture<>();
333         private AtomicReference<Flow.Subscriber<? super List<ByteBuffer>>> subscriberRef = new AtomicReference<>();
334         private final CompletionStage<Publisher<List<ByteBuffer>>> body =
335                 subscriptionCF.thenCompose((s) -> CompletableFuture.completedStage(this::subscribe));
336                 //CompletableFuture.completedStage(this::subscribe);

434         http2TestServer.start();
435         https2TestServer.start();
436     }
437 
438     @AfterTest
439     public void teardown() throws Exception {
440         Thread.sleep(100);
441         AssertionError fail = TRACKER.check(500);
442         try {
443             httpTestServer.stop();
444             httpsTestServer.stop();
445             http2TestServer.stop();
446             https2TestServer.stop();
447         } finally {
448             if (fail != null) {
449                 throw fail;
450             }
451         }
452     }
453 

















454     static final String WITH_BODY = "Lorem ipsum dolor sit amet, consectetur" +
455             " adipiscing elit, sed do eiusmod tempor incididunt ut labore et" +
456             " dolore magna aliqua. Ut enim ad minim veniam, quis nostrud" +
457             " exercitation ullamco laboris nisi ut aliquip ex ea" +
458             " commodo consequat. Duis aute irure dolor in reprehenderit in " +
459             "voluptate velit esse cillum dolore eu fugiat nulla pariatur." +
460             " Excepteur sint occaecat cupidatat non proident, sunt in culpa qui" +
461             " officia deserunt mollit anim id est laborum.";
462 
463     static class HTTP_FixedLengthHandler implements HttpTestHandler {
464         @Override
465         public void handle(HttpTestExchange t) throws IOException {
466             out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
467             try (InputStream is = t.getRequestBody()) {
468                 is.readAllBytes();
469             }
470             if (t.getRequestURI().getPath().endsWith("/withBody")) {
471                 byte[] bytes = WITH_BODY.getBytes(UTF_8);
472                 t.sendResponseHeaders(200, bytes.length);  // body
473                 try (OutputStream os = t.getResponseBody()) {

 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 /*
 25  * @test
 26  * @bug 8201186
 27  * @summary Tests an asynchronous BodySubscriber that completes
 28  *          immediately with a Publisher<List<ByteBuffer>>
 29  * @library /test/lib /test/jdk/java/net/httpclient/lib
 30  * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters
 31  * @run testng/othervm ResponsePublisher
 32  */
 33 
 34 import com.sun.net.httpserver.HttpExchange;
 35 import com.sun.net.httpserver.HttpHandler;
 36 import com.sun.net.httpserver.HttpServer;
 37 import com.sun.net.httpserver.HttpsConfigurator;
 38 import com.sun.net.httpserver.HttpsServer;
 39 import jdk.internal.net.http.common.OperationTrackers;
 40 import jdk.test.lib.net.SimpleSSLContext;
 41 import org.testng.annotations.AfterTest;
 42 import org.testng.annotations.BeforeTest;
 43 import org.testng.annotations.DataProvider;
 44 import org.testng.annotations.Test;
 45 
 46 import javax.net.ssl.SSLContext;
 47 import java.io.IOException;
 48 import java.io.InputStream;
 49 import java.io.OutputStream;
 50 import java.net.InetAddress;
 51 import java.net.InetSocketAddress;
 52 import java.net.URI;
 53 import java.net.http.HttpClient;
 54 import java.net.http.HttpHeaders;
 55 import java.net.http.HttpRequest;
 56 import java.net.http.HttpResponse;
 57 import java.net.http.HttpResponse.BodyHandler;
 58 import java.net.http.HttpResponse.BodyHandlers;
 59 import java.net.http.HttpResponse.BodySubscriber;

 84 public class ResponsePublisher implements HttpServerAdapters {
 85 
 86     SSLContext sslContext;
 87     HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
 88     HttpTestServer httpsTestServer;   // HTTPS/1.1
 89     HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
 90     HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
 91     String httpURI_fixed;
 92     String httpURI_chunk;
 93     String httpsURI_fixed;
 94     String httpsURI_chunk;
 95     String http2URI_fixed;
 96     String http2URI_chunk;
 97     String https2URI_fixed;
 98     String https2URI_chunk;
 99 
100     static final int ITERATION_COUNT = 3;
101     // a shared executor helps reduce the amount of threads created by the test
102     static final Executor executor = Executors.newCachedThreadPool();
103 
104     static final long start = System.nanoTime();
105 
106     public static String now() {
107         long now = System.nanoTime() - start;
108         long secs = now / 1000_000_000;
109         long mill = (now % 1000_000_000) / 1000_000;
110         long nan = now % 1000_000;
111         return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
112     }
113 
114     interface BHS extends Supplier<BodyHandler<Publisher<List<ByteBuffer>>>> {
115         static BHS of(BHS impl, String name) {
116             return new BHSImpl(impl, name);
117         }
118     }
119 
120     static final class BHSImpl implements BHS {
121         final BHS supplier;
122         final String name;
123         BHSImpl(BHS impl, String name) {
124             this.supplier = impl;
125             this.name = name;
126         }
127         @Override
128         public String toString() {
129             return name;
130         }
131 
132         @Override
133         public BodyHandler<Publisher<List<ByteBuffer>>> get() {

210             // Publisher<List<ByteBuffer>>
211             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
212             response.body().subscribe(ofString);
213 
214             BodySubscriber<String> ofString2 = BodySubscribers.ofString(UTF_8);
215             response.body().subscribe(ofString2);
216             try {
217                 ofString2.getBody().toCompletableFuture().join();
218                 throw new RuntimeException("Expected ISE not thrown");
219             } catch (CompletionException x) {
220                 Throwable cause = x.getCause();
221                 if (cause instanceof  IllegalStateException) {
222                     System.out.println("Got expected ISE: " + cause);
223                 } else {
224                     throw x;
225                 }
226             }
227             // Get the final result and compare it with the expected body
228             String body = ofString.getBody().toCompletableFuture().get();
229             assertEquals(body, "");
230             // ensure client closes before next iteration
231             if (!sameClient) {
232                 var tracker = TRACKER.getTracker(client);
233                 client = null;
234                 clientCleanup(tracker);
235             }
236         }
237     }
238 
239     @Test(dataProvider = "variants")
240     public void testNoBody(String uri, boolean sameClient, BHS handlers) throws Exception {
241         HttpClient client = null;
242         for (int i=0; i< ITERATION_COUNT; i++) {
243             if (!sameClient || client == null)
244                 client = newHttpClient();
245 
246             HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
247                     .build();
248             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
249             HttpResponse<Publisher<List<ByteBuffer>>> response = client.send(req, handler);
250             // We can reuse our BodySubscribers implementations to subscribe to the
251             // Publisher<List<ByteBuffer>>
252             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
253             // get the Publisher<List<ByteBuffer>> and
254             // subscribe to it.
255             response.body().subscribe(ofString);
256             // Get the final result and compare it with the expected body
257             String body = ofString.getBody().toCompletableFuture().get();
258             assertEquals(body, "");
259             // ensure client closes before next iteration
260             if (!sameClient) {
261                 var tracker = TRACKER.getTracker(client);
262                 client = null;
263                 clientCleanup(tracker);
264             }
265         }
266     }
267 
268     @Test(dataProvider = "variants")
269     public void testNoBodyAsync(String uri, boolean sameClient, BHS handlers) throws Exception {
270         HttpClient client = null;
271         for (int i=0; i< ITERATION_COUNT; i++) {
272             if (!sameClient || client == null)
273                 client = newHttpClient();
274 
275             HttpRequest req = HttpRequest.newBuilder(URI.create(uri))
276                     .build();
277             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
278             // We can reuse our BodySubscribers implementations to subscribe to the
279             // Publisher<List<ByteBuffer>>
280             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
281             CompletableFuture<String> result =
282                     client.sendAsync(req, handler).thenCompose(
283                             (responsePublisher) -> {
284                                 // get the Publisher<List<ByteBuffer>> and
285                                 // subscribe to it.
286                                 responsePublisher.body().subscribe(ofString);
287                                 return ofString.getBody();
288                             });
289             // Get the final result and compare it with the expected body
290             assertEquals(result.get(), "");
291             // ensure client closes before next iteration
292             if (!sameClient) {
293                 var tracker = TRACKER.getTracker(client);
294                 client = null;
295                 clientCleanup(tracker);
296             }
297         }
298     }
299 
300     @Test(dataProvider = "variants")
301     public void testAsString(String uri, boolean sameClient, BHS handlers) throws Exception {
302         HttpClient client = null;
303         for (int i=0; i< ITERATION_COUNT; i++) {
304             if (!sameClient || client == null)
305                 client = newHttpClient();
306 
307             HttpRequest req = HttpRequest.newBuilder(URI.create(uri+"/withBody"))
308                     .build();
309             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
310             HttpResponse<Publisher<List<ByteBuffer>>> response = client.send(req, handler);
311             // We can reuse our BodySubscribers implementations to subscribe to the
312             // Publisher<List<ByteBuffer>>
313             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
314             // get the Publisher<List<ByteBuffer>> and
315             // subscribe to it.
316             response.body().subscribe(ofString);
317             // Get the final result and compare it with the expected body
318             String body = ofString.getBody().toCompletableFuture().get();
319             assertEquals(body, WITH_BODY);
320             // ensure client closes before next iteration
321             if (!sameClient) {
322                 var tracker = TRACKER.getTracker(client);
323                 client = null;
324                 clientCleanup(tracker);
325             }
326         }
327     }
328 
329     @Test(dataProvider = "variants")
330     public void testAsStringAsync(String uri, boolean sameClient, BHS handlers) throws Exception {
331         HttpClient client = null;
332         for (int i=0; i< ITERATION_COUNT; i++) {
333             if (!sameClient || client == null)
334                 client = newHttpClient();
335 
336             HttpRequest req = HttpRequest.newBuilder(URI.create(uri+"/withBody"))
337                     .build();
338             BodyHandler<Publisher<List<ByteBuffer>>> handler = handlers.get();
339             // We can reuse our BodySubscribers implementations to subscribe to the
340             // Publisher<List<ByteBuffer>>
341             BodySubscriber<String> ofString = BodySubscribers.ofString(UTF_8);
342             CompletableFuture<String> result = client.sendAsync(req, handler)
343                     .thenCompose((responsePublisher) -> {
344                         // get the Publisher<List<ByteBuffer>> and
345                         // subscribe to it.
346                         responsePublisher.body().subscribe(ofString);
347                         return ofString.getBody();
348                     });
349             // Get the final result and compare it with the expected body
350             String body = result.get();
351             assertEquals(body, WITH_BODY);
352             // ensure client closes before next iteration
353             if (!sameClient) {
354                 var tracker = TRACKER.getTracker(client);
355                 client = null;
356                 clientCleanup(tracker);
357             }
358         }
359     }
360 
361     // A BodyHandler that returns PublishingBodySubscriber instances
362     static class PublishingBodyHandler implements BodyHandler<Publisher<List<ByteBuffer>>> {
363         @Override
364         public BodySubscriber<Publisher<List<ByteBuffer>>> apply(HttpResponse.ResponseInfo rinfo) {
365             assertEquals(rinfo.statusCode(), 200);
366             return new PublishingBodySubscriber();
367         }
368     }
369 
370     // A BodySubscriber that returns a Publisher<List<ByteBuffer>>
371     static class PublishingBodySubscriber implements BodySubscriber<Publisher<List<ByteBuffer>>> {
372         private final CompletableFuture<Flow.Subscription> subscriptionCF = new CompletableFuture<>();
373         private final CompletableFuture<Flow.Subscriber<? super List<ByteBuffer>>> subscribedCF = new CompletableFuture<>();
374         private AtomicReference<Flow.Subscriber<? super List<ByteBuffer>>> subscriberRef = new AtomicReference<>();
375         private final CompletionStage<Publisher<List<ByteBuffer>>> body =
376                 subscriptionCF.thenCompose((s) -> CompletableFuture.completedStage(this::subscribe));
377                 //CompletableFuture.completedStage(this::subscribe);

475         http2TestServer.start();
476         https2TestServer.start();
477     }
478 
479     @AfterTest
480     public void teardown() throws Exception {
481         Thread.sleep(100);
482         AssertionError fail = TRACKER.check(500);
483         try {
484             httpTestServer.stop();
485             httpsTestServer.stop();
486             http2TestServer.stop();
487             https2TestServer.stop();
488         } finally {
489             if (fail != null) {
490                 throw fail;
491             }
492         }
493     }
494 
495     // Wait for the client to be garbage collected.
496     // we use the ReferenceTracker API rather than HttpClient::close here,
497     // because we want to get some diagnosis if a client doesn't release
498     // its resources and terminates as expected
499     // By using the ReferenceTracker, we will get some diagnosis about what
500     // is keeping the client alive if it doesn't get GC'ed within the
501     // expected time frame.
502     public void clientCleanup(OperationTrackers.Tracker tracker){
503         System.gc();
504         System.out.println(now() + "waiting for client to shutdown: " + tracker.getName());
505         System.err.println(now() + "waiting for client to shutdown: " + tracker.getName());
506         var error = TRACKER.check(tracker, 10000);
507         if (error != null) throw error;
508         System.out.println(now() + "client shutdown normally: " + tracker.getName());
509         System.err.println(now() + "client shutdown normally: " + tracker.getName());
510     }
511 
512     static final String WITH_BODY = "Lorem ipsum dolor sit amet, consectetur" +
513             " adipiscing elit, sed do eiusmod tempor incididunt ut labore et" +
514             " dolore magna aliqua. Ut enim ad minim veniam, quis nostrud" +
515             " exercitation ullamco laboris nisi ut aliquip ex ea" +
516             " commodo consequat. Duis aute irure dolor in reprehenderit in " +
517             "voluptate velit esse cillum dolore eu fugiat nulla pariatur." +
518             " Excepteur sint occaecat cupidatat non proident, sunt in culpa qui" +
519             " officia deserunt mollit anim id est laborum.";
520 
521     static class HTTP_FixedLengthHandler implements HttpTestHandler {
522         @Override
523         public void handle(HttpTestExchange t) throws IOException {
524             out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
525             try (InputStream is = t.getRequestBody()) {
526                 is.readAllBytes();
527             }
528             if (t.getRequestURI().getPath().endsWith("/withBody")) {
529                 byte[] bytes = WITH_BODY.getBytes(UTF_8);
530                 t.sendResponseHeaders(200, bytes.length);  // body
531                 try (OutputStream os = t.getResponseBody()) {
< prev index next >