Path: blob/master/test/jdk/sun/net/www/protocol/https/ChunkedOutputStream.java
41159 views
/*1* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 502674526* @modules java.base/sun.net.www27* @build TestHttpsServer HttpCallback28* @run main/othervm ChunkedOutputStream29* @run main/othervm -Djava.net.preferIPv6Addresses=true ChunkedOutputStream30*31* SunJSSE does not support dynamic system properties, no way to re-use32* system properties in samevm/agentvm mode.33* @summary Cannot flush output stream when writing to an HttpUrlConnection34*/3536import java.io.*;37import java.net.*;38import javax.net.ssl.*;39import java.util.concurrent.atomic.AtomicInteger;4041public class ChunkedOutputStream implements HttpCallback {42/*43* Where do we find the keystores for ssl?44*/45static String pathToStores = "../../../../../javax/net/ssl/etc";46static String keyStoreFile = "keystore";47static String trustStoreFile = "truststore";48static String passwd = "passphrase";49static int count = 0;50static final AtomicInteger rogueCount = new AtomicInteger();5152static final String str1 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+53"1234567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"+54"1434567890abcdefkjsdlkjflkjsldkfjlsdkjflkj";5556static final String str2 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+57"1234567890";5859public void request(HttpTransaction req) {60try {61// this is needed (count++ doesn't work), 'cause we62// are doing concurrent tests63String path = req.getRequestURI().getPath();64if (path.equals("/d0")) {65count = 0;66} else if (path.equals("/d01")) {67count = 1;68} else if (path.equals("/d3")) {69count = 2;70} else if (path.equals("/d4") || path.equals("/d5")) {71count = 3;72} else if (path.equals("/d6")) {73count = 3;74} else if (path.equals("/d7")) {75count = 4;76} else if (path.equals("/d8")) {77count = 5;78}7980switch (count) {81case 0: /* test1 -- keeps conn alive */82case 1: /* test2 -- closes conn */83String reqbody = req.getRequestEntityBody();84if (!reqbody.equals(str1)) {85req.sendResponse(500, "Internal server error");86req.orderlyClose();87}88String chunk = req.getRequestHeader("Transfer-encoding");89if (!"chunked".equals(chunk)) {90req.sendResponse(501, "Internal server error");91req.orderlyClose();92}93req.setResponseEntityBody(reqbody);94if (count == 1) {95req.setResponseHeader("Connection", "close");96}97req.sendResponse(200, "OK");98if (count == 1) {99req.orderlyClose();100}101break;102case 2: /* test 3 */103reqbody = req.getRequestEntityBody();104if (!reqbody.equals(str2)) {105req.sendResponse(500, "Internal server error");106req.orderlyClose();107}108int clen = Integer.parseInt (109req.getRequestHeader("Content-length"));110if (clen != str2.length()) {111req.sendResponse(501, "Internal server error");112req.orderlyClose();113}114req.setResponseEntityBody (reqbody);115req.setResponseHeader("Connection", "close");116req.sendResponse(200, "OK");117req.orderlyClose();118break;119case 3: /* test 6 */120req.setResponseHeader("Location", "https://foo.bar/");121req.setResponseHeader("Connection", "close");122req.sendResponse(307, "Temporary Redirect");123req.orderlyClose();124break;125case 4: /* test 7 */126case 5: /* test 8 */127reqbody = req.getRequestEntityBody();128if (reqbody != null && !"".equals(reqbody)) {129req.sendResponse(501, "Internal server error");130req.orderlyClose();131}132req.setResponseHeader("Connection", "close");133req.sendResponse(200, "OK");134req.orderlyClose();135break;136default:137req.sendResponse(404, "Not Found");138req.orderlyClose();139break;140}141} catch (IOException e) {142e.printStackTrace();143}144}145146public boolean dropPlainTextConnections() {147System.out.println("Unrecognized SSL message, plaintext connection?");148System.out.println("TestHttpsServer receveived rogue connection: ignoring it.");149rogueCount.incrementAndGet();150return true;151}152153static void readAndCompare(InputStream is, String cmp) throws IOException {154int c;155byte buf[] = new byte[1024];156int off = 0;157int len = 1024;158while ((c=is.read(buf, off, len)) != -1) {159off += c;160len -= c;161}162String s1 = new String(buf, 0, off, "ISO8859_1");163if (!cmp.equals(s1)) {164throw new IOException("strings not same");165}166}167168/* basic smoke test: verify that server drops plain connections */169static void testPlainText(String authority) throws Exception {170URL url = new URL("http://" + authority + "/Donauschiffsgesellschaftskapitaenskajuete");171System.out.println("client opening connection to: " + url);172HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);173int rogue = rogueCount.get();174try {175int code = urlc.getResponseCode();176System.out.println("Unexpected response: " + code);177throw new AssertionError("Unexpected response: " + code);178} catch (SocketException x) {179// we expect that the server will drop the connection and180// close the accepted socket, so we should get a SocketException181// on the client side, and confirm that this::dropPlainTextConnections182// has ben called.183if (rogueCount.get() == rogue) throw x;184System.out.println("Got expected exception: " + x);185}186}187188/* basic chunked test (runs twice) */189190static void test1(String u) throws Exception {191URL url = new URL(u);192System.out.println("client opening connection to: " + u);193HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);194urlc.setChunkedStreamingMode(20);195urlc.setDoOutput(true);196urlc.setRequestMethod("POST");197OutputStream os = urlc.getOutputStream();198os.write(str1.getBytes());199os.close();200InputStream is = urlc.getInputStream();201readAndCompare(is, str1);202is.close();203}204205/* basic fixed length test */206207static void test3(String u) throws Exception {208URL url = new URL(u);209System.out.println("client opening connection to: " + u);210HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);211urlc.setFixedLengthStreamingMode(str2.length());212urlc.setDoOutput(true);213urlc.setRequestMethod("POST");214OutputStream os = urlc.getOutputStream();215os.write (str2.getBytes());216os.close();217InputStream is = urlc.getInputStream();218readAndCompare(is, str2);219is.close();220}221222/* write too few bytes */223224static void test4(String u) throws Exception {225URL url = new URL(u);226System.out.println("client opening connection to: " + u);227HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);228urlc.setFixedLengthStreamingMode(str2.length()+1);229urlc.setDoOutput(true);230urlc.setRequestMethod("POST");231OutputStream os = urlc.getOutputStream();232os.write(str2.getBytes());233try {234os.close();235throw new Exception("should have thrown IOException");236} catch (IOException e) {}237}238239/* write too many bytes */240241static void test5(String u) throws Exception {242URL url = new URL(u);243System.out.println("client opening connection to: " + u);244HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);245urlc.setFixedLengthStreamingMode(str2.length()-1);246urlc.setDoOutput(true);247urlc.setRequestMethod("POST");248OutputStream os = urlc.getOutputStream();249try {250os.write(str2.getBytes());251throw new Exception("should have thrown IOException");252} catch (IOException e) {}253}254255/* check for HttpRetryException on redirection */256257static void test6(String u) throws Exception {258URL url = new URL(u);259System.out.println("client opening connection to: " + u);260HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);261urlc.setChunkedStreamingMode(20);262urlc.setDoOutput(true);263urlc.setRequestMethod("POST");264OutputStream os = urlc.getOutputStream();265os.write(str1.getBytes());266os.close();267try {268InputStream is = urlc.getInputStream();269throw new Exception("should have gotten HttpRetryException");270} catch (HttpRetryException e) {271if (e.responseCode() != 307) {272throw new Exception("Wrong response code " + e.responseCode());273}274if (!e.getLocation().equals("https://foo.bar/")) {275throw new Exception("Wrong location " + e.getLocation());276}277}278}279280/* next two tests send zero length posts */281282static void test7(String u) throws Exception {283URL url = new URL(u);284System.out.println("client opening connection to: " + u);285HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);286urlc.setChunkedStreamingMode(20);287urlc.setDoOutput(true);288urlc.setRequestMethod("POST");289OutputStream os = urlc.getOutputStream();290os.close();291int ret = urlc.getResponseCode();292if (ret != 200) {293throw new Exception("Expected 200: got " + ret);294}295}296297static void test8(String u) throws Exception {298URL url = new URL(u);299System.out.println("client opening connection to: " + u);300HttpURLConnection urlc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);301urlc.setFixedLengthStreamingMode(0);302urlc.setDoOutput(true);303urlc.setRequestMethod("POST");304OutputStream os = urlc.getOutputStream();305os.close();306int ret = urlc.getResponseCode();307if (ret != 200) {308throw new Exception("Expected 200: got " + ret);309}310}311312static TestHttpsServer server;313314public static void main(String[] args) throws Exception {315// setup properties to do ssl316String keyFilename =317System.getProperty("test.src", "./") + "/" + pathToStores +318"/" + keyStoreFile;319String trustFilename =320System.getProperty("test.src", "./") + "/" + pathToStores +321"/" + trustStoreFile;322323InetAddress loopback = InetAddress.getLoopbackAddress();324325HostnameVerifier reservedHV =326HttpsURLConnection.getDefaultHostnameVerifier();327try {328System.setProperty("javax.net.ssl.keyStore", keyFilename);329System.setProperty("javax.net.ssl.keyStorePassword", passwd);330System.setProperty("javax.net.ssl.trustStore", trustFilename);331System.setProperty("javax.net.ssl.trustStorePassword", passwd);332HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());333334try {335server = new TestHttpsServer(336new ChunkedOutputStream(), 1, 10, loopback, 0);337System.out.println("Server started: listening on: " + server.getAuthority());338testPlainText(server.getAuthority());339// the test server doesn't support keep-alive yet340// test1("http://" + server.getAuthority() + "/d0");341test1("https://" + server.getAuthority() + "/d01");342test3("https://" + server.getAuthority() + "/d3");343test4("https://" + server.getAuthority() + "/d4");344test5("https://" + server.getAuthority() + "/d5");345test6("https://" + server.getAuthority() + "/d6");346test7("https://" + server.getAuthority() + "/d7");347test8("https://" + server.getAuthority() + "/d8");348} catch (Exception e) {349if (server != null) {350server.terminate();351}352throw e;353}354server.terminate();355} finally {356HttpsURLConnection.setDefaultHostnameVerifier(reservedHV);357}358}359360static class NameVerifier implements HostnameVerifier {361public boolean verify(String hostname, SSLSession session) {362return true;363}364}365366public static void except(String s) {367server.terminate();368throw new RuntimeException(s);369}370}371372373