Path: blob/master/test/jdk/java/net/URLConnection/ZeroContentLength.java
41149 views
/*1* Copyright (c) 2001, 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 450741226* @bug 450699827* @summary Check that a 304 "Not-Modified" response from a server28* doesn't cause http client to close a keep-alive29* connection.30* Check that a content-length of 0 results in an31* empty input stream.32* @library /test/lib33* @run main ZeroContentLength34* @run main/othervm -Djava.net.preferIPv6Addresses=true ZeroContentLength35*/3637import java.net.*;38import java.io.*;39import jdk.test.lib.net.URIBuilder;4041public class ZeroContentLength {4243/*44* Is debugging enabled - start with -d to enable.45*/46static boolean debug = false;4748static void debug(String msg) {49if (debug)50System.out.println(msg);51}5253/*54* The response string and content-length that55* the server should return;56*/57static String response;58static int contentLength;5960static synchronized void setResponse(String rsp, int cl) {61response = rsp;62contentLength = cl;63}6465static synchronized String getResponse() {66return response;67}6869static synchronized int getContentLength() {70return contentLength;71}7273/*74* Worker thread to service single connection - can service75* multiple http requests on same connection.76*/77class Worker extends Thread {78Socket s;79int id;8081Worker(Socket s, int id) {82this.s = s;83this.id = id;84}8586final int CR = '\r';87final int LF = '\n';8889public void run() {90try {9192s.setSoTimeout(2000);93int max = 20; // there should only be 20 connections94InputStream in = new BufferedInputStream(s.getInputStream());9596for (;;) {97// read entire request from client, until CR LF CR LF98int c, total=0;99100try {101while ((c = in.read()) > 0) {102total++;103if (c == CR) {104if ((c = in.read()) > 0) {105total++;106if (c == LF) {107if ((c = in.read()) > 0) {108total++;109if (c == CR) {110if ((c = in.read()) > 0) {111total++;112if (c == LF) {113break;114}115}116}117}118}119}120}121122}123} catch (SocketTimeoutException e) {}124125debug("worker " + id +126": Read request from client " +127"(" + total + " bytes).");128129if (total == 0) {130debug("worker: " + id + ": Shutdown");131return;132}133134// response to client135PrintStream out = new PrintStream(136new BufferedOutputStream(137s.getOutputStream() ));138139out.print("HTTP/1.1 " + getResponse() + "\r\n");140int clen = getContentLength();141if (clen >= 0) {142out.print("Content-Length: " + clen +143"\r\n");144}145out.print("\r\n");146for (int i=0; i<clen; i++) {147out.write( (byte)'.' );148}149out.flush();150151debug("worked " + id +152": Sent response to client, length: " + clen);153154if (--max == 0) {155s.close();156return;157}158}159160} catch (Exception e) {161e.printStackTrace();162} finally {163try {164s.close();165} catch (Exception e) { }166}167}168}169170/*171* Server thread to accept connection and create worker threads172* to service each connection.173*/174class Server extends Thread {175ServerSocket ss;176int connectionCount;177boolean shutdown = false;178179Server(ServerSocket ss) {180this.ss = ss;181}182183public synchronized int connectionCount() {184return connectionCount;185}186187public synchronized void shutdown() {188shutdown = true;189}190191public void run() {192try {193ss.setSoTimeout(2000);194195for (;;) {196Socket s;197try {198debug("server: Waiting for connections");199s = ss.accept();200} catch (SocketTimeoutException te) {201synchronized (this) {202if (shutdown) {203debug("server: Shuting down.");204return;205}206}207continue;208}209210int id;211synchronized (this) {212id = connectionCount++;213}214215Worker w = new Worker(s, id);216w.start();217debug("server: Started worker " + id);218}219220} catch (Exception e) {221e.printStackTrace();222} finally {223try {224ss.close();225} catch (Exception e) { }226}227}228}229230/*231* Make a single http request and return the content length232* received. Also do sanity check to ensure that the233* content-length header matches the total received on234* the input stream.235*/236int doRequest(String uri) throws Exception {237URL url = new URL(uri);238HttpURLConnection http = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);239240int cl = http.getContentLength();241242InputStream in = http.getInputStream();243byte b[] = new byte[100];244int total = 0;245int n;246do {247n = in.read(b);248if (n > 0) total += n;249} while (n > 0);250in.close();251252if (cl >= 0 && total != cl) {253System.err.println("content-length header indicated: " + cl);254System.err.println("Actual received: " + total);255throw new Exception("Content-length didn't match actual received");256}257258return total;259}260261262/*263* Send http requests to "server" and check that they all264* use the same network connection and that the content265* length corresponds to the content length expected.266* stream.267*/268ZeroContentLength() throws Exception {269270/* start the server */271ServerSocket ss = new ServerSocket();272ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));273Server svr = new Server(ss);274svr.start();275276String uri = URIBuilder.newBuilder()277.scheme("http")278.host(ss.getInetAddress())279.port(ss.getLocalPort())280.path("/foo.html")281.build().toString();282283int expectedTotal = 0;284int actualTotal = 0;285286System.out.println("**********************************");287System.out.println("200 OK, content-length:1024 ...");288setResponse("200 OK", 1024);289for (int i=0; i<5; i++) {290actualTotal += doRequest(uri);291expectedTotal += 1024;292}293294System.out.println("**********************************");295System.out.println("200 OK, content-length:0 ...");296setResponse("200 OK", 0);297for (int i=0; i<5; i++) {298actualTotal += doRequest(uri);299}300301System.out.println("**********************************");302System.out.println("304 Not-Modified, (no content-length) ...");303setResponse("304 Not-Modifed", -1);304for (int i=0; i<5; i++) {305actualTotal += doRequest(uri);306}307308System.out.println("**********************************");309System.out.println("204 No-Content, (no content-length) ...");310setResponse("204 No-Content", -1);311for (int i=0; i<5; i++) {312actualTotal += doRequest(uri);313}314315// shutdown server - we're done.316svr.shutdown();317318System.out.println("**********************************");319320if (actualTotal == expectedTotal) {321System.out.println("Passed: Actual total equal to expected total");322} else {323throw new Exception("Actual total != Expected total!!!");324}325326int cnt = svr.connectionCount();327if (cnt == 1) {328System.out.println("Passed: Only 1 connection established");329} else {330throw new Exception("Test failed: Number of connections " +331"established: " + cnt + " - see log for details.");332}333}334335public static void main(String args[]) throws Exception {336337if (args.length > 0 && args[0].equals("-d")) {338debug = true;339}340341new ZeroContentLength();342}343344}345346347