1 /* 2 * Copyright (c) 2006, 2007, 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 6488669 6595324 6993490 27 * @run main/othervm ChunkedErrorStream 28 * @summary Chunked ErrorStream tests 29 */ 30 31 import java.net.*; 32 import java.io.*; 33 import com.sun.net.httpserver.*; 34 35 /** 36 * Part 1: 6488669 37 * 1) Http server that responds with an error code (>=400) 38 * and a chunked response body. It also indicates that 39 * the connection will be closed. 40 * 2) Client sends request to server and tries to 41 * getErrorStream(). Some data must be able to be read 42 * from the errorStream. 43 * 44 * Part 2: 6595324 45 * 1) Http server that responds with an error code (>=400) 46 * and a chunked response body greater than 47 * sun.net.http.errorstream.bufferSize, 4K + 10 bytes. 48 * 2) Client sends request to server and tries to 49 * getErrorStream(). 4K + 10 bytes must be read from 50 * the errorStream. 51 * 52 * Part 3: 6993490 53 * Reuse persistent connection from part 2, the error stream 54 * buffering will have set a reduced timeout on the socket and 55 * tried to reset it to the default, infinity. Client must not 56 * throw a timeout exception. If it does, it indicates that the 57 * default timeout was not reset correctly. 58 * If no timeout exception is thrown, it does not guarantee that 59 * the timeout was reset correctly, as there is a potential race 60 * between the sleeping server and the client thread. Typically, 61 * 1000 millis has been enought to reliable reproduce this problem 62 * since the error stream buffering sets the timeout to 60 millis. 63 */ 64 65 public class ChunkedErrorStream 66 { 67 com.sun.net.httpserver.HttpServer httpServer; 68 69 static { 70 // Enable ErrorStream buffering 71 System.getProperties().setProperty("sun.net.http.errorstream.enableBuffering", "true"); 72 73 // No need to set this as 4K is the default 74 // System.getProperties().setProperty("sun.net.http.errorstream.bufferSize", "4096"); 75 } 76 77 public static void main(String[] args) { 78 new ChunkedErrorStream(); 79 } 80 81 public ChunkedErrorStream() { 82 try { 83 startHttpServer(); 84 doClient(); 85 } catch (IOException ioe) { 86 ioe.printStackTrace(); 87 } finally { 88 httpServer.stop(1); 89 } 90 } 91 92 void doClient() { 93 for (int times=0; times<3; times++) { 94 HttpURLConnection uc = null; 95 try { 96 InetSocketAddress address = httpServer.getAddress(); 97 String URLStr = "http://localhost:" + address.getPort() + "/test/"; 98 if (times == 0) { 99 URLStr += "first"; 100 } else { 101 URLStr += "second"; 102 } 103 104 System.out.println("Trying " + URLStr); 105 URL url = new URL(URLStr); 106 uc = (HttpURLConnection)url.openConnection(); 107 uc.getInputStream(); 108 109 throw new RuntimeException("Failed: getInputStream should throw and IOException"); 110 } catch (IOException e) { 111 if (e instanceof SocketTimeoutException) { 112 e.printStackTrace(); 113 throw new RuntimeException("Failed: SocketTimeoutException should not happen"); 114 } 115 116 // This is what we expect to happen. 117 InputStream es = uc.getErrorStream(); 118 byte[] ba = new byte[1024]; 119 int count = 0, ret; 120 try { 121 while ((ret = es.read(ba)) != -1) 122 count += ret; 123 es.close(); 124 } catch (IOException ioe) { 125 ioe.printStackTrace(); 126 } 127 128 if (count == 0) 129 throw new RuntimeException("Failed: ErrorStream returning 0 bytes"); 130 131 if (times >= 1 && count != (4096+10)) 132 throw new RuntimeException("Failed: ErrorStream returning " + count + 133 " bytes. Expecting " + (4096+10)); 134 135 System.out.println("Read " + count + " bytes from the errorStream"); 136 } 137 } 138 } 139 140 /** 141 * Http Server 142 */ 143 void startHttpServer() throws IOException { 144 httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0); 145 146 // create HttpServer context 147 httpServer.createContext("/test/first", new FirstHandler()); 148 httpServer.createContext("/test/second", new SecondHandler()); 149 150 httpServer.start(); 151 } 152 153 class FirstHandler implements HttpHandler { 154 public void handle(HttpExchange t) throws IOException { 155 InputStream is = t.getRequestBody(); 156 byte[] ba = new byte[1024]; 157 while (is.read(ba) != -1); 158 is.close(); 159 160 Headers resHeaders = t.getResponseHeaders(); 161 resHeaders.add("Connection", "close"); 162 t.sendResponseHeaders(404, 0); 163 OutputStream os = t.getResponseBody(); 164 165 // actual data doesn't matter. Just send 2K worth. 166 byte b = 'a'; 167 for (int i=0; i<2048; i++) 168 os.write(b); 169 170 os.close(); 171 t.close(); 172 } 173 } 174 175 static class SecondHandler implements HttpHandler { 176 /* count greater than 0, slow response */ 177 static int count = 0; 178 179 public void handle(HttpExchange t) throws IOException { 180 InputStream is = t.getRequestBody(); 181 byte[] ba = new byte[1024]; 182 while (is.read(ba) != -1); 183 is.close(); 184 185 if (count > 0) { 186 System.out.println("server sleeping..."); 187 try { Thread.sleep(1000); } catch(InterruptedException e) {} 188 } 189 count++; 190 191 t.sendResponseHeaders(404, 0); 192 OutputStream os = t.getResponseBody(); 193 194 // actual data doesn't matter. Just send more than 4K worth 195 byte b = 'a'; 196 for (int i=0; i<(4096+10); i++) 197 os.write(b); 198 199 os.close(); 200 t.close(); 201 } 202 } 203 } --- EOF ---