Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/net/URLConnection/ZeroContentLength.java
38812 views
/*1* Copyright (c) 2001, 2010, 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*/33import java.net.*;34import java.io.*;3536public class ZeroContentLength {3738/*39* Is debugging enabled - start with -d to enable.40*/41static boolean debug = false;4243static void debug(String msg) {44if (debug)45System.out.println(msg);46}4748/*49* The response string and content-length that50* the server should return;51*/52static String response;53static int contentLength;5455static synchronized void setResponse(String rsp, int cl) {56response = rsp;57contentLength = cl;58}5960static synchronized String getResponse() {61return response;62}6364static synchronized int getContentLength() {65return contentLength;66}6768/*69* Worker thread to service single connection - can service70* multiple http requests on same connection.71*/72class Worker extends Thread {73Socket s;74int id;7576Worker(Socket s, int id) {77this.s = s;78this.id = id;79}8081final int CR = '\r';82final int LF = '\n';8384public void run() {85try {8687s.setSoTimeout(2000);88int max = 20; // there should only be 20 connections89InputStream in = new BufferedInputStream(s.getInputStream());9091for (;;) {92// read entire request from client, until CR LF CR LF93int c, total=0;9495try {96while ((c = in.read()) > 0) {97total++;98if (c == CR) {99if ((c = in.read()) > 0) {100total++;101if (c == LF) {102if ((c = in.read()) > 0) {103total++;104if (c == CR) {105if ((c = in.read()) > 0) {106total++;107if (c == LF) {108break;109}110}111}112}113}114}115}116117}118} catch (SocketTimeoutException e) {}119120debug("worker " + id +121": Read request from client " +122"(" + total + " bytes).");123124if (total == 0) {125debug("worker: " + id + ": Shutdown");126return;127}128129// response to client130PrintStream out = new PrintStream(131new BufferedOutputStream(132s.getOutputStream() ));133134out.print("HTTP/1.1 " + getResponse() + "\r\n");135int clen = getContentLength();136if (clen >= 0) {137out.print("Content-Length: " + clen +138"\r\n");139}140out.print("\r\n");141for (int i=0; i<clen; i++) {142out.write( (byte)'.' );143}144out.flush();145146debug("worked " + id +147": Sent response to client, length: " + clen);148149if (--max == 0) {150s.close();151return;152}153}154155} catch (Exception e) {156e.printStackTrace();157} finally {158try {159s.close();160} catch (Exception e) { }161}162}163}164165/*166* Server thread to accept connection and create worker threads167* to service each connection.168*/169class Server extends Thread {170ServerSocket ss;171int connectionCount;172boolean shutdown = false;173174Server(ServerSocket ss) {175this.ss = ss;176}177178public synchronized int connectionCount() {179return connectionCount;180}181182public synchronized void shutdown() {183shutdown = true;184}185186public void run() {187try {188ss.setSoTimeout(2000);189190for (;;) {191Socket s;192try {193debug("server: Waiting for connections");194s = ss.accept();195} catch (SocketTimeoutException te) {196synchronized (this) {197if (shutdown) {198debug("server: Shuting down.");199return;200}201}202continue;203}204205int id;206synchronized (this) {207id = connectionCount++;208}209210Worker w = new Worker(s, id);211w.start();212debug("server: Started worker " + id);213}214215} catch (Exception e) {216e.printStackTrace();217} finally {218try {219ss.close();220} catch (Exception e) { }221}222}223}224225/*226* Make a single http request and return the content length227* received. Also do sanity check to ensure that the228* content-length header matches the total received on229* the input stream.230*/231int doRequest(String uri) throws Exception {232URL url = new URL(uri);233HttpURLConnection http = (HttpURLConnection)url.openConnection();234235int cl = http.getContentLength();236237InputStream in = http.getInputStream();238byte b[] = new byte[100];239int total = 0;240int n;241do {242n = in.read(b);243if (n > 0) total += n;244} while (n > 0);245in.close();246247if (cl >= 0 && total != cl) {248System.err.println("content-length header indicated: " + cl);249System.err.println("Actual received: " + total);250throw new Exception("Content-length didn't match actual received");251}252253return total;254}255256257/*258* Send http requests to "server" and check that they all259* use the same network connection and that the content260* length corresponds to the content length expected.261* stream.262*/263ZeroContentLength() throws Exception {264265/* start the server */266ServerSocket ss = new ServerSocket(0);267Server svr = new Server(ss);268svr.start();269270String uri = "http://localhost:" +271Integer.toString(ss.getLocalPort()) +272"/foo.html";273274int expectedTotal = 0;275int actualTotal = 0;276277System.out.println("**********************************");278System.out.println("200 OK, content-length:1024 ...");279setResponse("200 OK", 1024);280for (int i=0; i<5; i++) {281actualTotal += doRequest(uri);282expectedTotal += 1024;283}284285System.out.println("**********************************");286System.out.println("200 OK, content-length:0 ...");287setResponse("200 OK", 0);288for (int i=0; i<5; i++) {289actualTotal += doRequest(uri);290}291292System.out.println("**********************************");293System.out.println("304 Not-Modified, (no content-length) ...");294setResponse("304 Not-Modifed", -1);295for (int i=0; i<5; i++) {296actualTotal += doRequest(uri);297}298299System.out.println("**********************************");300System.out.println("204 No-Content, (no content-length) ...");301setResponse("204 No-Content", -1);302for (int i=0; i<5; i++) {303actualTotal += doRequest(uri);304}305306// shutdown server - we're done.307svr.shutdown();308309System.out.println("**********************************");310311if (actualTotal == expectedTotal) {312System.out.println("Passed: Actual total equal to expected total");313} else {314throw new Exception("Actual total != Expected total!!!");315}316317int cnt = svr.connectionCount();318if (cnt == 1) {319System.out.println("Passed: Only 1 connection established");320} else {321throw new Exception("Test failed: Number of connections " +322"established: " + cnt + " - see log for details.");323}324}325326public static void main(String args[]) throws Exception {327328if (args.length > 0 && args[0].equals("-d")) {329debug = true;330}331332new ZeroContentLength();333}334335}336337338