< prev index next >
1 /*
2 * Copyright (c) 2015, 2016, 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 /**
25 * @test
26 * @bug 8087112
27 * @library /lib/testlibrary/
28 * @build jdk.testlibrary.SimpleSSLContext ProxyServer
29 * @compile ../../../com/sun/net/httpserver/LogFilter.java
30 * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
31 * @run main/othervm SmokeTest
32 */
33
34 //package javaapplication16;
35
36 import com.sun.net.httpserver.*;
37 import java.net.*;
38 import java.net.http.*;
39 import java.io.*;
40 import java.util.concurrent.*;
41 import javax.net.ssl.*;
42 import java.nio.file.*;
43 import java.util.HashSet;
44 import java.util.LinkedList;
45 import java.util.List;
46 import java.util.Random;
47 import jdk.testlibrary.SimpleSSLContext;
48 import static java.net.http.HttpRequest.*;
49 import static java.net.http.HttpResponse.*;
50 import java.util.logging.ConsoleHandler;
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53
54 /**
55 * * Basic smoke test for Http/1.1 client
56 * - basic request response
57 * - request body POST
58 * - response body GET
59 * - redirect
60 * - chunked request/response
61 * - SSL
62 * - proxies
63 * - 100 continue
64 * - check keep alive appears to be working
65 * - cancel of long request
66 *
67 * Uses a FileServerHandler serving a couple of known files
68 * in docs directory.
69 */
70 public class SmokeTest {
71 static SSLContext ctx;
72 static HttpServer s1 ;
73 static HttpsServer s2;
74 static ExecutorService executor;
75 static int port;
76 static int httpsport;
77 static String httproot;
78 static String httpsroot;
79 static HttpClient client;
80 static ProxyServer proxy;
81 static int proxyPort;
82 static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure;
83 static RedirectHandler redirectHandler, redirectHandlerSecure;
84 static DelayHandler delayHandler;
85 final static String midSizedFilename = "/files/notsobigfile.txt";
86 final static String smallFilename = "/files/smallfile.txt";
87 static Path midSizedFile;
88 static Path smallFile;
89 static String fileroot;
90
91 static String getFileContent(String path) throws IOException {
92 FileInputStream fis = new FileInputStream(path);
93 byte[] buf = new byte[2000];
94 StringBuilder sb = new StringBuilder();
95 int n;
96 while ((n=fis.read(buf)) != -1) {
97 sb.append(new String(buf, 0, n, "US-ASCII"));
98 }
99 return sb.toString();
100 }
101
102 public static void main(String[] args) throws Exception {
103 initServer();
104 fileroot = System.getProperty ("test.src", ".")+ "/docs";
105 midSizedFile = Paths.get(fileroot + midSizedFilename);
106 smallFile = Paths.get(fileroot + smallFilename);
107
108 client = HttpClient.create()
109 .sslContext(ctx)
110 .followRedirects(HttpClient.Redirect.ALWAYS)
111 .executorService(Executors.newCachedThreadPool())
112 .build();
113
114 try {
115 test1(httproot + "files/foo.txt", true);
116
117 test1(httproot + "files/foo.txt", false);
118 test1(httpsroot + "files/foo.txt", true);
119 test1(httpsroot + "files/foo.txt", false);
120 test2(httproot + "echo/foo", "This is a short test");
121 test2(httpsroot + "echo/foo", "This is a short test");
122
123 test3(httproot + "redirect/foo.txt");
124 test3(httpsroot + "redirect/foo.txt");
125 test4(httproot + "files/foo.txt");
126 test4(httpsroot + "files/foo.txt");
127 test5(httproot + "echo/foo", true);
128 test5(httpsroot + "echo/foo", true);
129 test5(httproot + "echo/foo", false);
130 test5(httpsroot + "echo/foo", false);
131
132 test6(httproot + "echo/foo", true);
133 test6(httpsroot + "echo/foo", true);
134 test6(httproot + "echo/foo", false);
135 test6(httpsroot + "echo/foo", false);
136
137 test7(httproot + "keepalive/foo");
138
139 test8(httproot + "files/foo.txt", true);
140 test8(httproot + "files/foo.txt", false);
141 test8(httpsroot + "files/foo.txt", true);
142 test8(httpsroot + "files/foo.txt", false);
143 // disabled test9();
144
145 test10(httproot + "redirecterror/foo.txt");
146
147 test10(httpsroot + "redirecterror/foo.txt");
148
149 test11(httproot + "echo/foo");
150 test11(httpsroot + "echo/foo");
151 //test12(httproot + "delay/foo", delayHandler);
152
153 } finally {
154 s1.stop(0);
155 s2.stop(0);
156 proxy.close();
157 executor.shutdownNow();
158 client.executorService().shutdownNow();
159 }
160 }
161
162 static class Auth extends java.net.Authenticator {
163 volatile int count = 0;
164 @Override
165 protected PasswordAuthentication getPasswordAuthentication() {
166 if (count++ == 0) {
167 return new PasswordAuthentication("user", "passwd".toCharArray());
168 } else {
169 return new PasswordAuthentication("user", "goober".toCharArray());
170 }
171 }
172 int count() {
173 return count;
174 }
175 }
176
177 // Basic test
178 static void test1(String target, boolean fixedLen) throws Exception {
179 System.out.print("test1: " + target);
180 URI uri = new URI(target);
181
182 HttpRequest.Builder builder = client.request(uri)
183 .body(noBody());
184
185 if (fixedLen) {
186 builder.header("XFixed", "yes");
187 }
188
189 HttpResponse response = builder.GET().response();
190
191 String body = response.body(asString());
192 if (!body.equals("This is foo.txt\r\n")) {
193 throw new RuntimeException();
194 }
195
196 // repeat async
197 response = builder.GET().responseAsync().join();
198
199 body = response.body(asString());
200 if (!body.equals("This is foo.txt\r\n")) {
201 throw new RuntimeException();
202 }
203 System.out.println(" OK");
204 }
205
206 // POST use echo to check reply
207 static void test2(String s, String body) throws Exception {
208 System.out.print("test2: " + s);
209 URI uri = new URI(s);
210
211 HttpResponse response = client.request(uri)
212 .body(fromString(body))
213 .POST()
214 .response();
215
216 if (response.statusCode() != 200) {
217 throw new RuntimeException(
218 "Expected 200, got [ " + response.statusCode() + " ]");
219 }
220 String reply = response.body(asString());
221 if (!reply.equals(body)) {
222 throw new RuntimeException(
223 "Body mismatch: expected [" + body + "], got [" + reply + "]");
224 }
225 System.out.println(" OK");
226 }
227
228 // Redirect
229 static void test3(String s) throws Exception {
230 System.out.print("test3: " + s);
231 URI uri = new URI(s);
232 RedirectHandler handler = uri.getScheme().equals("https")
233 ? redirectHandlerSecure : redirectHandler;
234
235 HttpResponse response = client.request(uri)
236 .body(noBody())
237 .GET()
238 .response();
239
240 if (response.statusCode() != 200) {
241 throw new RuntimeException(
242 "Expected 200, got [ " + response.statusCode() + " ]");
243 } else {
244 response.body(HttpResponse.asFile(Paths.get("redir1.txt")));
245 }
246
247 Path downloaded = Paths.get("redir1.txt");
248 if (Files.size(downloaded) != Files.size(midSizedFile)) {
249 throw new RuntimeException("Size mismatch");
250 }
251
252 System.out.printf(" (count: %d) ", handler.count());
253 // repeat with async api
254
255 handler.reset();
256
257 response = client.request(uri)
258 .body(noBody())
259 .GET()
260 .responseAsync()
261 .join();
262
263 if (response.statusCode() != 200) {
264 throw new RuntimeException(
265 "Expected 200, got [ " + response.statusCode() + " ]");
266 } else {
267 response.body(HttpResponse.asFile(Paths.get("redir2.txt")));
268 }
269
270 downloaded = Paths.get("redir2.txt");
271 if (Files.size(downloaded) != Files.size(midSizedFile)) {
272 throw new RuntimeException("Size mismatch 2");
273 }
274 System.out.printf(" (count: %d) ", handler.count());
275 System.out.println(" OK");
276 }
277
278 // Proxies
279 static void test4(String s) throws Exception {
280 System.out.print("test4: " + s);
281 URI uri = new URI(s);
282 InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort);
283 String filename = fileroot + uri.getPath();
284
285 HttpClient cl = HttpClient.create()
286 .proxy(ProxySelector.of(proxyAddr))
287 .sslContext(ctx)
288 .build();
289
290 CompletableFuture<String> fut = cl.request(uri)
291 .body(noBody())
292 .GET()
293 .responseAsync()
294 .thenCompose((HttpResponse response) ->
295 response.bodyAsync(asString())
296 );
297
298 String body = fut.get(5, TimeUnit.HOURS);
299
300 String fc = getFileContent(filename);
301
302 if (!body.equals(fc)) {
303 throw new RuntimeException(
304 "Body mismatch: expected [" + body + "], got [" + fc + "]");
305 }
306 cl.executorService().shutdownNow();
307 System.out.println(" OK");
308 }
309
310 // 100 Continue: use echo target
311 static void test5(String target, boolean fixedLen) throws Exception {
312 System.out.print("test5: " + target);
313 URI uri = new URI(target);
314 String requestBody = generateString(12 * 1024 + 13);
315
316 HttpRequest.Builder builder = client.request(uri)
317 .expectContinue(true)
318 .body(fromString(requestBody));
319
320 if (fixedLen) {
321 builder.header("XFixed", "yes");
322 }
323
324 HttpResponse response = builder.GET().response();
325
326 String body = response.body(asString());
327
328 if (!body.equals(requestBody)) {
329 throw new RuntimeException(
330 "Body mismatch: expected [" + body + "], got [" + body + "]");
331 }
332 System.out.println(" OK");
333 }
334
335 // use echo
336 static void test6(String target, boolean fixedLen) throws Exception {
337 System.out.print("test6: " + target);
338 URI uri = new URI(target);
339 String requestBody = generateString(12 * 1024 + 3);
340
341 HttpRequest.Builder builder = client.request(uri)
342 .body(noBody());
343
344 if (fixedLen) {
345 builder.header("XFixed", "yes");
346 }
347
348 HttpResponse response = builder.GET().response();
349
350 if (response.statusCode() != 200) {
351 throw new RuntimeException(
352 "Expected 200, got [ " + response.statusCode() + " ]");
353 }
354
355 String responseBody = response.body(asString());
356
357 if (responseBody.equals(requestBody)) {
358 throw new RuntimeException(
359 "Body mismatch: expected [" + requestBody + "], got [" + responseBody + "]");
360 }
361 System.out.println(" OK");
362 }
363
364 @SuppressWarnings("rawtypes")
365 static void test7(String target) throws Exception {
366 System.out.print("test7: " + target);
367
368 // First test
369 URI uri = new URI(target);
370 for (int i=0; i<4; i++) {
371 HttpResponse r = client.request(uri)
372 .body(noBody())
373 .GET()
374 .response();
375 String body = r.body(asString());
376 if (!body.equals("OK")) {
377 throw new RuntimeException("Expected OK, got: " + body);
378 }
379 }
380
381 // Second test: 4 x parallel
382 List<CompletableFuture<HttpResponse>> futures = new LinkedList<>();
383 for (int i=0; i<4; i++) {
384 futures.add(client.request(uri)
385 .body(noBody())
386 .GET()
387 .responseAsync());
388 }
389 // all sent?
390 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
391 .join();
392
393 List<CompletableFuture<String>> futureBodies = new LinkedList<>();
394 for (int i=0; i<4; i++) {
395 futureBodies.add(futures.get(i)
396 .join()
397 .bodyAsync(asString()));
398 }
399 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
400 .join();
401
402 for (CompletableFuture<String> future : futureBodies) {
403 String body = future.get();
404 if (!body.equals("OK")) {
405 throw new RuntimeException("Expected OK, got: " + body);
406 }
407 }
408
409 // Third test: Multiple of 4 parallel requests
410 BlockingQueue<String> q = new LinkedBlockingQueue<>();
411 for (int i=0; i<4; i++) {
412 client.request(uri)
413 .body(noBody())
414 .GET()
415 .responseAsync()
416 .thenApply((HttpResponse resp) -> {
417 String body = resp.body(asString());
418 putQ(q, body);
419 return body;
420 });
421 }
422 // we've sent four requests. Now, just send another request
423 // as each response is received. The idea is to ensure that
424 // only four sockets ever get used.
425
426 for (int i=0; i<100; i++) {
427 // block until response received
428 String body = takeQ(q);
429 if (!body.equals("OK")) {
430 throw new RuntimeException(body);
431 }
432 client.request(uri)
433 .body(noBody())
434 .GET()
435 .responseAsync()
436 .thenApply((HttpResponse resp) -> {
437 String body1 = resp.body(asString());
438 putQ(q, body1);
439 return body1;
440 });
441 }
442 // should be four left
443 for (int i=0; i<4; i++) {
444 takeQ(q);
445 }
446 System.out.println(" OK");
447 }
448
449 static String takeQ(BlockingQueue<String> q) {
450 String r = null;
451 try {
452 r = q.take();
453 } catch (InterruptedException e) {}
454
455 return r;
456 }
457
458 static void putQ(BlockingQueue<String> q, String o) {
459 try {
460 q.put(o);
461 } catch (InterruptedException e) {
462 // can't happen
463 }
464 }
465
466 static void test8(String target, boolean fixedLen) throws Exception {
467 System.out.print("test8: " + target);
468 URI uri = new URI(target);
469
470 HttpRequest.Builder builder = client.request(uri)
471 .body(noBody());
472
473 if (fixedLen) {
474 builder.header("XFixed", "yes");
475 }
476
477 HttpResponse response = builder.GET().response();
478
479 StringBuilder sb = new StringBuilder();
480
481 InputStream is = response.body(asInputStream());
482 int c;
483 byte[] buf = new byte[2048];
484 while ((c = is.read(buf)) != -1) {
485 for (int i=0; i<c; i++)
486 sb.append((char)buf[i]);
487 }
488 is.close();
489 String body = sb.toString();
490
491 if (!body.equals("This is foo.txt\r\n")) {
492 throw new RuntimeException("Expected \"This is foo.txt\", got: " + body);
493 }
494 System.out.println(" OK");
495 }
496
497 // Chunked output stream
498 static void test11(String target) throws Exception {
499 System.out.print("test11: " + target);
500 URI uri = new URI(target);
501
502 FileInputStream file = new FileInputStream(smallFile.toFile());
503
504 HttpRequest.Builder builder = client.request(uri)
505 .body(HttpRequest.fromInputStream(file));
506 HttpResponse response = builder.POST().response();
507
508 if (response.statusCode() != 200) {
509 throw new RuntimeException("Wrong response code");
510 }
511
512 Path download = Paths.get("test11.txt");
513 download.toFile().delete();
514 response.body(HttpResponse.asFile(download));
515
516 if (Files.size(download) != Files.size(smallFile)) {
517 System.out.println("Original size: " + Files.size(smallFile));
518 System.out.println("Downloaded size: " + Files.size(download));
519 throw new RuntimeException("Size mismatch");
520 }
521 System.out.println(" OK");
522 }
523
524 // cancel
525 /*
526 static void test12(String target, DelayHandler h) throws Exception {
527 System.out.print("test12: " + target);
528 URI uri = new URI(target);
529
530 HttpRequest.Builder builder = client
531 .request(uri)
532 .body(HttpRequest.fromString("Hello world"));
533
534 HttpRequest request = builder
535 .GET();
536 request.sendAsync();
537 h.barrier1().await();
538 // request has been processed
539 CompletableFuture<HttpResponse> cf = request.responseAsync();
540 request.cancel();
541 h.barrier2().await();
542 try {
543 HttpResponse r = cf.get();
544 throw new RuntimeException("failed 2");
545 } catch (Exception e) {
546 }
547 System.out.println(" OK");
548 }
549 */
550 static void delay(int seconds) {
551 try {
552 Thread.sleep(seconds * 1000);
553 } catch (InterruptedException e) {
554 }
555 }
556 /*
557 // test won't work until sending fully decoupled from receiving in impl
558 static void test9() throws Exception {
559 System.out.print("test9: ");
560 UploadServer up = new UploadServer(1000 * 1000);
561 int size = up.size();
562 String u = "http://127.0.0.1:" + up.port() + "/";
563 URI uri = new URI(u);
564
565 HttpRequest request = client
566 .request(uri)
567 .body(new HttpRequestBodyProcessor() {
568 @Override
569 public ByteBuffer onRequestBodyChunk(ByteBuffer b) throws IOException {
570 // slow things down
571 delay(1);
572 b.position(b.limit()); // fill it
573 return b;
574 }
575 @Override
576 public long onRequestStart(HttpRequest req) throws IOException {
577 return size;
578 }
579 })
580 .PUT();
581
582 CompletableFuture<HttpRequest> cf1 = request.sendAsync();
583 CompletableFuture<HttpResponse> cf = request.responseAsync();
584
585 HttpResponse resp = cf.get(1, TimeUnit.MINUTES);
586 if (resp.statusCode() != 201) {
587 throw new RuntimeException("failed: wrong response code");
588 }
589 delay(2); // allow some data to be sent
590 request.cancel();
591 delay(1);
592 if (up.failed()) {
593 throw new RuntimeException("failed to cancel request");
594 }
595 System.out.println(" OK");
596 }
597 */
598 // Redirect loop: return an error after a certain number of redirects
599 static void test10(String s) throws Exception {
600 System.out.print("test10: " + s);
601 URI uri = new URI(s);
602 RedirectErrorHandler handler = uri.getScheme().equals("https")
603 ? redirectErrorHandlerSecure : redirectErrorHandler;
604
605 CompletableFuture<HttpResponse> cf = client.request(uri)
606 .body(noBody())
607 .GET()
608 .responseAsync();
609
610 try {
611 HttpResponse response = cf.join();
612 throw new RuntimeException("Exepected Completion Exception");
613 } catch (CompletionException e) {
614 //System.out.println(e);
615 }
616
617 System.out.printf(" (Calls %d) ", handler.count());
618 System.out.println(" OK");
619 }
620
621 static final int NUM = 50;
622
623 static Random random = new Random();
624 static final String alphabet = "ABCDEFGHIJKLMNOPQRST";
625
626 static char randomChar() {
627 return alphabet.charAt(random.nextInt(alphabet.length()));
628 }
629
630 static String generateString(int length) {
631 StringBuilder sb = new StringBuilder(length);
632 for (int i=0; i<length; i++) {
633 sb.append(randomChar());
634 }
635 return sb.toString();
636 }
637
638 static void initServer() throws Exception {
639 Logger logger = Logger.getLogger("com.sun.net.httpserver");
640 ConsoleHandler ch = new ConsoleHandler();
641 logger.setLevel(Level.ALL);
642 ch.setLevel(Level.ALL);
643 logger.addHandler(ch);
644
645 String root = System.getProperty ("test.src")+ "/docs";
646 InetSocketAddress addr = new InetSocketAddress (0);
647 s1 = HttpServer.create (addr, 0);
648 if (s1 instanceof HttpsServer) {
649 throw new RuntimeException ("should not be httpsserver");
650 }
651 s2 = HttpsServer.create (addr, 0);
652 HttpHandler h = new FileServerHandler(root);
653
654 HttpContext c1 = s1.createContext("/files", h);
655 HttpContext c2 = s2.createContext("/files", h);
656 HttpContext c3 = s1.createContext("/echo", new EchoHandler());
657 redirectHandler = new RedirectHandler("/redirect");
658 redirectHandlerSecure = new RedirectHandler("/redirect");
659 HttpContext c4 = s1.createContext("/redirect", redirectHandler);
660 HttpContext c41 = s2.createContext("/redirect", redirectHandlerSecure);
661 HttpContext c5 = s2.createContext("/echo", new EchoHandler());
662 HttpContext c6 = s1.createContext("/keepalive", new KeepAliveHandler());
663 redirectErrorHandler = new RedirectErrorHandler("/redirecterror");
664 redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror");
665 HttpContext c7 = s1.createContext("/redirecterror", redirectErrorHandler);
666 HttpContext c71 = s2.createContext("/redirecterror", redirectErrorHandlerSecure);
667 delayHandler = new DelayHandler();
668 HttpContext c8 = s1.createContext("/delay", delayHandler);
669 HttpContext c81 = s2.createContext("/delay", delayHandler);
670
671 executor = Executors.newCachedThreadPool();
672 s1.setExecutor(executor);
673 s2.setExecutor(executor);
674 ctx = new SimpleSSLContext().get();
675 s2.setHttpsConfigurator(new HttpsConfigurator(ctx));
676 s1.start();
677 s2.start();
678
679 port = s1.getAddress().getPort();
680 System.out.println("HTTP server port = " + port);
681 httpsport = s2.getAddress().getPort();
682 System.out.println("HTTPS server port = " + httpsport);
683 httproot = "http://127.0.0.1:" + port + "/";
684 httpsroot = "https://127.0.0.1:" + httpsport + "/";
685
686 proxy = new ProxyServer(0, false);
687 proxyPort = proxy.getPort();
688 System.out.println("Proxy port = " + proxyPort);
689 }
690 }
691
692 class UploadServer extends Thread {
693 int statusCode;
694 ServerSocket ss;
695 int port;
696 int size;
697 Object lock;
698 boolean failed = false;
699
700 UploadServer(int size) throws IOException {
701 this.statusCode = statusCode;
702 this.size = size;
703 ss = new ServerSocket(0);
704 port = ss.getLocalPort();
705 lock = new Object();
706 }
707
708 int port() {
709 return port;
710 }
711
712 int size() {
713 return size;
714 }
715
716 // wait a sec before calling this
717 boolean failed() {
718 synchronized(lock) {
719 return failed;
720 }
721 }
722
723 @Override
724 public void run () {
725 int nbytes = 0;
726 Socket s = null;
727
728 synchronized(lock) {
729 try {
730 s = ss.accept();
731
732 InputStream is = s.getInputStream();
733 OutputStream os = s.getOutputStream();
734 os.write("HTTP/1.1 201 OK\r\nContent-length: 0\r\n\r\n".getBytes());
735 int n;
736 byte[] buf = new byte[8000];
737 while ((n=is.read(buf)) != -1) {
738 nbytes += n;
739 }
740 } catch (IOException e) {
741 System.out.println ("read " + nbytes);
742 System.out.println ("size " + size);
743 failed = nbytes >= size;
744 } finally {
745 try {
746 ss.close();
747 if (s != null)
748 s.close();
749 } catch (IOException e) {}
750 }
751 }
752 }
753 }
754
755 class RedirectHandler implements HttpHandler {
756 String root;
757 volatile int count = 0;
758
759 RedirectHandler(String root) {
760 this.root = root;
761 }
762
763 @Override
764 public synchronized void handle(HttpExchange t)
765 throws IOException
766 {
767 byte[] buf = new byte[2048];
768 try (InputStream is = t.getRequestBody()) {
769 while (is.read(buf) != -1) ;
770 }
771
772 Headers responseHeaders = t.getResponseHeaders();
773
774 if (count++ < 1) {
775 responseHeaders.add("Location", root + "/foo/" + count);
776 } else {
777 responseHeaders.add("Location", SmokeTest.midSizedFilename);
778 }
779 t.sendResponseHeaders(301, -1);
780 t.close();
781 }
782
783 int count() {
784 return count;
785 }
786
787 void reset() {
788 count = 0;
789 }
790 }
791
792 class RedirectErrorHandler implements HttpHandler {
793 String root;
794 volatile int count = 1;
795
796 RedirectErrorHandler(String root) {
797 this.root = root;
798 }
799
800 synchronized int count() {
801 return count;
802 }
803
804 synchronized void increment() {
805 count++;
806 }
807
808 @Override
809 public synchronized void handle (HttpExchange t)
810 throws IOException
811 {
812 byte[] buf = new byte[2048];
813 try (InputStream is = t.getRequestBody()) {
814 while (is.read(buf) != -1) ;
815 }
816
817 Headers map = t.getResponseHeaders();
818 String redirect = root + "/foo/" + Integer.toString(count);
819 increment();
820 map.add("Location", redirect);
821 t.sendResponseHeaders(301, -1);
822 t.close();
823 }
824 }
825
826 class Util {
827 static byte[] readAll(InputStream is) throws IOException {
828 byte[] buf = new byte[1024];
829 byte[] result = new byte[0];
830
831 while (true) {
832 int n = is.read(buf);
833 if (n > 0) {
834 byte[] b1 = new byte[result.length + n];
835 System.arraycopy(result, 0, b1, 0, result.length);
836 System.arraycopy(buf, 0, b1, result.length, n);
837 result = b1;
838 } else if (n == -1) {
839 return result;
840 }
841 }
842 }
843 }
844
845 class DelayHandler implements HttpHandler {
846
847 CyclicBarrier bar1 = new CyclicBarrier(2);
848 CyclicBarrier bar2 = new CyclicBarrier(2);
849 CyclicBarrier bar3 = new CyclicBarrier(2);
850
851 CyclicBarrier barrier1() {
852 return bar1;
853 }
854
855 CyclicBarrier barrier2() {
856 return bar2;
857 }
858
859 @Override
860 public synchronized void handle(HttpExchange he) throws IOException {
861 byte[] buf = Util.readAll(he.getRequestBody());
862 try {
863 bar1.await();
864 bar2.await();
865 } catch (Exception e) {}
866 he.sendResponseHeaders(200, -1); // will probably fail
867 he.close();
868 }
869
870 }
871
872 // check for simple hardcoded sequence and use remote address
873 // to check.
874 // First 4 requests executed in sequence (should use same connection/address)
875 // Next 4 requests parallel (should use different addresses)
876 // Then send 4 requests in parallel x 100 times (same four addresses used all time)
877
878 class KeepAliveHandler implements HttpHandler {
879 volatile int counter = 0;
880
881 HashSet<Integer> portSet = new HashSet<>();
882
883 volatile int[] ports = new int[4];
884
885 void sleep(int n) {
886 try {
887 Thread.sleep(n);
888 } catch (InterruptedException e) {}
889 }
890
891 @Override
892 public synchronized void handle (HttpExchange t)
893 throws IOException
894 {
895 int remotePort = t.getRemoteAddress().getPort();
896 String result = "OK";
897
898 int n = counter++;
899 /// First test
900 if (n < 4) {
901 ports[n] = remotePort;
902 }
903 if (n == 3) {
904 // check all values in ports[] are the same
905 if (ports[0] != ports[1] || ports[2] != ports[3]
906 || ports[0] != ports[2]) {
907 result = "Error " + Integer.toString(n);
908 System.out.println(result);
909 }
910 }
911 // Second test
912 if (n >=4 && n < 8) {
913 // delay to ensure ports are different
914 sleep(500);
915 ports[n-4] = remotePort;
916 }
917 if (n == 7) {
918 // should be all different
919 if (ports[0] == ports[1] || ports[2] == ports[3]
920 || ports[0] == ports[2]) {
921 result = "Error " + Integer.toString(n);
922 System.out.println(result);
923 System.out.printf("Ports: %d, %d, %d, %d\n", ports[0], ports[1], ports[2], ports[3]);
924 }
925 // setup for third test
926 for (int i=0; i<4; i++) {
927 portSet.add(ports[i]);
928 }
929 }
930 // Third test
931 if (n > 7) {
932 // just check that port is one of the ones in portSet
933 if (!portSet.contains(remotePort)) {
934 System.out.println ("UNEXPECTED REMOTE PORT " + remotePort);
935 result = "Error " + Integer.toString(n);
936 System.out.println(result);
937 }
938 }
939 byte[] buf = new byte[2048];
940
941 try (InputStream is = t.getRequestBody()) {
942 while (is.read(buf) != -1) ;
943 }
944 t.sendResponseHeaders(200, result.length());
945 OutputStream o = t.getResponseBody();
946 o.write(result.getBytes("US-ASCII"));
947 t.close();
948 }
949 }
< prev index next >