1 /* 2 * Copyright (c) 2004, 2019, 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 5026745 27 * @modules java.base/sun.net.www 28 * @build TestHttpsServer HttpCallback 29 * @run main/othervm ChunkedOutputStream 30 * @run main/othervm -Djava.net.preferIPv6Addresses=true ChunkedOutputStream 31 * 32 * SunJSSE does not support dynamic system properties, no way to re-use 33 * system properties in samevm/agentvm mode. 34 * @summary Cannot flush output stream when writing to an HttpUrlConnection 35 */ 36 37 import java.io.*; 38 import java.net.*; 39 import javax.net.ssl.*; 40 41 public class ChunkedOutputStream implements HttpCallback { 42 /* 43 * Where do we find the keystores for ssl? 44 */ 45 static String pathToStores = "../../../../../javax/net/ssl/etc"; 46 static String keyStoreFile = "keystore"; 47 static String trustStoreFile = "truststore"; 48 static String passwd = "passphrase"; 49 static int count = 0; 50 51 static final String str1 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+ 52 "1234567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"+ 53 "1434567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"; 54 55 static final String str2 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+ 56 "1234567890"; 57 58 public void request(HttpTransaction req) { 59 try { 60 // this is needed (count++ doesn't work), 'cause we 61 // are doing concurrent tests 62 String path = req.getRequestURI().getPath(); 63 if (path.equals("/d0")) { 64 count = 0; 65 } else if (path.equals("/d01")) { 66 count = 1; 67 } else if (path.equals("/d3")) { 68 count = 2; 69 } else if (path.equals("/d4") || path.equals("/d5")) { 70 count = 3; 71 } else if (path.equals("/d6")) { 72 count = 3; 73 } else if (path.equals("/d7")) { 74 count = 4; 75 } else if (path.equals("/d8")) { 76 count = 5; 77 } 78 79 switch (count) { 80 case 0: /* test1 -- keeps conn alive */ 81 case 1: /* test2 -- closes conn */ 82 String reqbody = req.getRequestEntityBody(); 83 if (!reqbody.equals(str1)) { 84 req.sendResponse(500, "Internal server error"); 85 req.orderlyClose(); 86 } 87 String chunk = req.getRequestHeader("Transfer-encoding"); 88 if (!"chunked".equals(chunk)) { 89 req.sendResponse(501, "Internal server error"); 90 req.orderlyClose(); 91 } 92 req.setResponseEntityBody(reqbody); 93 if (count == 1) { 94 req.setResponseHeader("Connection", "close"); 95 } 96 req.sendResponse(200, "OK"); 97 if (count == 1) { 98 req.orderlyClose(); 99 } 100 break; 101 case 2: /* test 3 */ 102 reqbody = req.getRequestEntityBody(); 103 if (!reqbody.equals(str2)) { 104 req.sendResponse(500, "Internal server error"); 105 req.orderlyClose(); 106 } 107 int clen = Integer.parseInt ( 108 req.getRequestHeader("Content-length")); 109 if (clen != str2.length()) { 110 req.sendResponse(501, "Internal server error"); 111 req.orderlyClose(); 112 } 113 req.setResponseEntityBody (reqbody); 114 req.setResponseHeader("Connection", "close"); 115 req.sendResponse(200, "OK"); 116 req.orderlyClose(); 117 break; 118 case 3: /* test 6 */ 119 req.setResponseHeader("Location", "https://foo.bar/"); 120 req.setResponseHeader("Connection", "close"); 121 req.sendResponse(307, "Temporary Redirect"); 122 req.orderlyClose(); 123 break; 124 case 4: /* test 7 */ 125 case 5: /* test 8 */ 126 reqbody = req.getRequestEntityBody(); 127 if (reqbody != null && !"".equals(reqbody)) { 128 req.sendResponse(501, "Internal server error"); 129 req.orderlyClose(); 130 } 131 req.setResponseHeader("Connection", "close"); 132 req.sendResponse(200, "OK"); 133 req.orderlyClose(); 134 break; 135 } 136 } catch (IOException e) { 137 e.printStackTrace(); 138 } 139 } 140 141 public boolean closeOnException(Exception ex) { 142 if (ex instanceof SSLException) { 143 if (ex.toString().contains("Unrecognized SSL message, plaintext connection?")) { 144 System.out.println("TestHttpsServer receveived rogue connection: " + ex); 145 System.out.println("Ignoring rogue connection..."); 146 return true; 147 } 148 } 149 return false; 150 } 151 152 static void readAndCompare(InputStream is, String cmp) throws IOException { 153 int c; 154 byte buf[] = new byte[1024]; 155 int off = 0; 156 int len = 1024; 157 while ((c=is.read(buf, off, len)) != -1) { 158 off += c; 159 len -= c; 160 } 161 String s1 = new String(buf, 0, off, "ISO8859_1"); 162 if (!cmp.equals(s1)) { 163 throw new IOException("strings not same"); 164 } 165 } 166 167 /* basic chunked test (runs twice) */ 168 169 static void test1(String u) throws Exception { 170 URL url = new URL(u); 171 System.out.println("client opening connection to: " + u); 172 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 173 urlc.setChunkedStreamingMode(20); 174 urlc.setDoOutput(true); 175 urlc.setRequestMethod("POST"); 176 OutputStream os = urlc.getOutputStream(); 177 os.write(str1.getBytes()); 178 os.close(); 179 InputStream is = urlc.getInputStream(); 180 readAndCompare(is, str1); 181 is.close(); 182 } 183 184 /* basic fixed length test */ 185 186 static void test3(String u) throws Exception { 187 URL url = new URL(u); 188 System.out.println("client opening connection to: " + u); 189 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 190 urlc.setFixedLengthStreamingMode(str2.length()); 191 urlc.setDoOutput(true); 192 urlc.setRequestMethod("POST"); 193 OutputStream os = urlc.getOutputStream(); 194 os.write (str2.getBytes()); 195 os.close(); 196 InputStream is = urlc.getInputStream(); 197 readAndCompare(is, str2); 198 is.close(); 199 } 200 201 /* write too few bytes */ 202 203 static void test4(String u) throws Exception { 204 URL url = new URL(u); 205 System.out.println("client opening connection to: " + u); 206 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 207 urlc.setFixedLengthStreamingMode(str2.length()+1); 208 urlc.setDoOutput(true); 209 urlc.setRequestMethod("POST"); 210 OutputStream os = urlc.getOutputStream(); 211 os.write(str2.getBytes()); 212 try { 213 os.close(); 214 throw new Exception("should have thrown IOException"); 215 } catch (IOException e) {} 216 } 217 218 /* write too many bytes */ 219 220 static void test5(String u) throws Exception { 221 URL url = new URL(u); 222 System.out.println("client opening connection to: " + u); 223 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 224 urlc.setFixedLengthStreamingMode(str2.length()-1); 225 urlc.setDoOutput(true); 226 urlc.setRequestMethod("POST"); 227 OutputStream os = urlc.getOutputStream(); 228 try { 229 os.write(str2.getBytes()); 230 throw new Exception("should have thrown IOException"); 231 } catch (IOException e) {} 232 } 233 234 /* check for HttpRetryException on redirection */ 235 236 static void test6(String u) throws Exception { 237 URL url = new URL(u); 238 System.out.println("client opening connection to: " + u); 239 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 240 urlc.setChunkedStreamingMode(20); 241 urlc.setDoOutput(true); 242 urlc.setRequestMethod("POST"); 243 OutputStream os = urlc.getOutputStream(); 244 os.write(str1.getBytes()); 245 os.close(); 246 try { 247 InputStream is = urlc.getInputStream(); 248 throw new Exception("should have gotten HttpRetryException"); 249 } catch (HttpRetryException e) { 250 if (e.responseCode() != 307) { 251 throw new Exception("Wrong response code " + e.responseCode()); 252 } 253 if (!e.getLocation().equals("https://foo.bar/")) { 254 throw new Exception("Wrong location " + e.getLocation()); 255 } 256 } 257 } 258 259 /* next two tests send zero length posts */ 260 261 static void test7(String u) throws Exception { 262 URL url = new URL(u); 263 System.out.println("client opening connection to: " + u); 264 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 265 urlc.setChunkedStreamingMode(20); 266 urlc.setDoOutput(true); 267 urlc.setRequestMethod("POST"); 268 OutputStream os = urlc.getOutputStream(); 269 os.close(); 270 int ret = urlc.getResponseCode(); 271 if (ret != 200) { 272 throw new Exception("Expected 200: got " + ret); 273 } 274 } 275 276 static void test8(String u) throws Exception { 277 URL url = new URL(u); 278 System.out.println("client opening connection to: " + u); 279 HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 280 urlc.setFixedLengthStreamingMode(0); 281 urlc.setDoOutput(true); 282 urlc.setRequestMethod("POST"); 283 OutputStream os = urlc.getOutputStream(); 284 os.close(); 285 int ret = urlc.getResponseCode(); 286 if (ret != 200) { 287 throw new Exception("Expected 200: got " + ret); 288 } 289 } 290 291 static TestHttpsServer server; 292 293 public static void main(String[] args) throws Exception { 294 // setup properties to do ssl 295 String keyFilename = 296 System.getProperty("test.src", "./") + "/" + pathToStores + 297 "/" + keyStoreFile; 298 String trustFilename = 299 System.getProperty("test.src", "./") + "/" + pathToStores + 300 "/" + trustStoreFile; 301 302 InetAddress loopback = InetAddress.getLoopbackAddress(); 303 304 HostnameVerifier reservedHV = 305 HttpsURLConnection.getDefaultHostnameVerifier(); 306 try { 307 System.setProperty("javax.net.ssl.keyStore", keyFilename); 308 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 309 System.setProperty("javax.net.ssl.trustStore", trustFilename); 310 System.setProperty("javax.net.ssl.trustStorePassword", passwd); 311 HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); 312 313 try { 314 server = new TestHttpsServer( 315 new ChunkedOutputStream(), 1, 10, loopback, 0); 316 System.out.println("Server started: listening on: " + server.getAuthority()); 317 // the test server doesn't support keep-alive yet 318 // test1("http://" + server.getAuthority() + "/d0"); 319 test1("https://" + server.getAuthority() + "/d01"); 320 test3("https://" + server.getAuthority() + "/d3"); 321 test4("https://" + server.getAuthority() + "/d4"); 322 test5("https://" + server.getAuthority() + "/d5"); 323 test6("https://" + server.getAuthority() + "/d6"); 324 test7("https://" + server.getAuthority() + "/d7"); 325 test8("https://" + server.getAuthority() + "/d8"); 326 } catch (Exception e) { 327 if (server != null) { 328 server.terminate(); 329 } 330 throw e; 331 } 332 server.terminate(); 333 } finally { 334 HttpsURLConnection.setDefaultHostnameVerifier(reservedHV); 335 } 336 } 337 338 static class NameVerifier implements HostnameVerifier { 339 public boolean verify(String hostname, SSLSession session) { 340 return true; 341 } 342 } 343 344 public static void except(String s) { 345 server.terminate(); 346 throw new RuntimeException(s); 347 } 348 }