test/jdk/java/net/URLConnection/ZeroContentLength.java
changeset 47216 71c04702a3d5
parent 7668 d4a77089c587
child 55047 3131927311ee
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2001, 2010, 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 4507412
       
    27  * @bug 4506998
       
    28  * @summary Check that a 304 "Not-Modified" response from a server
       
    29  *          doesn't cause http client to close a keep-alive
       
    30  *          connection.
       
    31  *          Check that a content-length of 0 results in an
       
    32  *          empty input stream.
       
    33  */
       
    34 import java.net.*;
       
    35 import java.io.*;
       
    36 
       
    37 public class ZeroContentLength {
       
    38 
       
    39     /*
       
    40      * Is debugging enabled - start with -d to enable.
       
    41      */
       
    42     static boolean debug = false;
       
    43 
       
    44     static void debug(String msg) {
       
    45         if (debug)
       
    46             System.out.println(msg);
       
    47     }
       
    48 
       
    49     /*
       
    50      * The response string and content-length that
       
    51      * the server should return;
       
    52      */
       
    53     static String response;
       
    54     static int contentLength;
       
    55 
       
    56     static synchronized void setResponse(String rsp, int cl) {
       
    57         response = rsp;
       
    58         contentLength = cl;
       
    59     }
       
    60 
       
    61     static synchronized String getResponse() {
       
    62         return response;
       
    63     }
       
    64 
       
    65     static synchronized int getContentLength() {
       
    66         return contentLength;
       
    67     }
       
    68 
       
    69     /*
       
    70      * Worker thread to service single connection - can service
       
    71      * multiple http requests on same connection.
       
    72      */
       
    73     class Worker extends Thread {
       
    74         Socket s;
       
    75         int id;
       
    76 
       
    77         Worker(Socket s, int id) {
       
    78             this.s = s;
       
    79             this.id = id;
       
    80         }
       
    81 
       
    82         final int CR = '\r';
       
    83         final int LF = '\n';
       
    84 
       
    85         public void run() {
       
    86             try {
       
    87 
       
    88                 s.setSoTimeout(2000);
       
    89                 int max = 20; // there should only be 20 connections
       
    90                 InputStream in = new BufferedInputStream(s.getInputStream());
       
    91 
       
    92                 for (;;) {
       
    93                     // read entire request from client, until CR LF CR LF
       
    94                     int c, total=0;
       
    95 
       
    96                     try {
       
    97                         while ((c = in.read()) > 0) {
       
    98                             total++;
       
    99                             if (c == CR) {
       
   100                                 if ((c = in.read()) > 0) {
       
   101                                     total++;
       
   102                                     if (c == LF) {
       
   103                                         if ((c = in.read()) > 0) {
       
   104                                             total++;
       
   105                                             if (c == CR) {
       
   106                                                 if ((c = in.read()) > 0) {
       
   107                                                     total++;
       
   108                                                     if (c == LF) {
       
   109                                                         break;
       
   110                                                     }
       
   111                                                 }
       
   112                                             }
       
   113                                         }
       
   114                                     }
       
   115                                 }
       
   116                             }
       
   117 
       
   118                         }
       
   119                     } catch (SocketTimeoutException e) {}
       
   120 
       
   121                     debug("worker " + id +
       
   122                         ": Read request from client " +
       
   123                         "(" + total + " bytes).");
       
   124 
       
   125                     if (total == 0) {
       
   126                         debug("worker: " + id + ": Shutdown");
       
   127                         return;
       
   128                     }
       
   129 
       
   130                     // response to client
       
   131                     PrintStream out = new PrintStream(
       
   132                                         new BufferedOutputStream(
       
   133                                                 s.getOutputStream() ));
       
   134 
       
   135                     out.print("HTTP/1.1 " + getResponse() + "\r\n");
       
   136                     int clen = getContentLength();
       
   137                     if (clen >= 0) {
       
   138                         out.print("Content-Length: " + clen +
       
   139                                     "\r\n");
       
   140                     }
       
   141                     out.print("\r\n");
       
   142                     for (int i=0; i<clen; i++) {
       
   143                         out.write( (byte)'.' );
       
   144                     }
       
   145                     out.flush();
       
   146 
       
   147                     debug("worked " + id +
       
   148                         ": Sent response to client, length: " + clen);
       
   149 
       
   150                     if (--max == 0) {
       
   151                         s.close();
       
   152                         return;
       
   153                     }
       
   154                 }
       
   155 
       
   156             } catch (Exception e) {
       
   157                 e.printStackTrace();
       
   158             } finally {
       
   159                 try {
       
   160                     s.close();
       
   161                 } catch (Exception e) { }
       
   162             }
       
   163         }
       
   164     }
       
   165 
       
   166     /*
       
   167      * Server thread to accept connection and create worker threads
       
   168      * to service each connection.
       
   169      */
       
   170     class Server extends Thread {
       
   171         ServerSocket ss;
       
   172         int connectionCount;
       
   173         boolean shutdown = false;
       
   174 
       
   175         Server(ServerSocket ss) {
       
   176             this.ss = ss;
       
   177         }
       
   178 
       
   179         public synchronized int connectionCount() {
       
   180             return connectionCount;
       
   181         }
       
   182 
       
   183         public synchronized void shutdown() {
       
   184             shutdown = true;
       
   185         }
       
   186 
       
   187         public void run() {
       
   188             try {
       
   189                 ss.setSoTimeout(2000);
       
   190 
       
   191                 for (;;) {
       
   192                     Socket s;
       
   193                     try {
       
   194                         debug("server: Waiting for connections");
       
   195                         s = ss.accept();
       
   196                     } catch (SocketTimeoutException te) {
       
   197                         synchronized (this) {
       
   198                             if (shutdown) {
       
   199                                 debug("server: Shuting down.");
       
   200                                 return;
       
   201                             }
       
   202                         }
       
   203                         continue;
       
   204                     }
       
   205 
       
   206                     int id;
       
   207                     synchronized (this) {
       
   208                         id = connectionCount++;
       
   209                     }
       
   210 
       
   211                     Worker w = new Worker(s, id);
       
   212                     w.start();
       
   213                     debug("server: Started worker " + id);
       
   214                 }
       
   215 
       
   216             } catch (Exception e) {
       
   217                 e.printStackTrace();
       
   218             } finally {
       
   219                 try {
       
   220                     ss.close();
       
   221                 } catch (Exception e) { }
       
   222             }
       
   223         }
       
   224     }
       
   225 
       
   226     /*
       
   227      * Make a single http request and return the content length
       
   228      * received. Also do sanity check to ensure that the
       
   229      * content-length header matches the total received on
       
   230      * the input stream.
       
   231      */
       
   232     int doRequest(String uri) throws Exception {
       
   233         URL url = new URL(uri);
       
   234         HttpURLConnection http = (HttpURLConnection)url.openConnection();
       
   235 
       
   236         int cl = http.getContentLength();
       
   237 
       
   238         InputStream in = http.getInputStream();
       
   239         byte b[] = new byte[100];
       
   240         int total = 0;
       
   241         int n;
       
   242         do {
       
   243             n = in.read(b);
       
   244             if (n > 0) total += n;
       
   245         } while (n > 0);
       
   246         in.close();
       
   247 
       
   248         if (cl >= 0 && total != cl) {
       
   249             System.err.println("content-length header indicated: " + cl);
       
   250             System.err.println("Actual received: " + total);
       
   251             throw new Exception("Content-length didn't match actual received");
       
   252         }
       
   253 
       
   254         return total;
       
   255     }
       
   256 
       
   257 
       
   258     /*
       
   259      * Send http requests to "server" and check that they all
       
   260      * use the same network connection and that the content
       
   261      * length corresponds to the content length expected.
       
   262      * stream.
       
   263      */
       
   264     ZeroContentLength() throws Exception {
       
   265 
       
   266         /* start the server */
       
   267         ServerSocket ss = new ServerSocket(0);
       
   268         Server svr = new Server(ss);
       
   269         svr.start();
       
   270 
       
   271         String uri = "http://localhost:" +
       
   272                      Integer.toString(ss.getLocalPort()) +
       
   273                      "/foo.html";
       
   274 
       
   275         int expectedTotal = 0;
       
   276         int actualTotal = 0;
       
   277 
       
   278         System.out.println("**********************************");
       
   279         System.out.println("200 OK, content-length:1024 ...");
       
   280         setResponse("200 OK", 1024);
       
   281         for (int i=0; i<5; i++) {
       
   282             actualTotal += doRequest(uri);
       
   283             expectedTotal += 1024;
       
   284         }
       
   285 
       
   286         System.out.println("**********************************");
       
   287         System.out.println("200 OK, content-length:0 ...");
       
   288         setResponse("200 OK", 0);
       
   289         for (int i=0; i<5; i++) {
       
   290             actualTotal += doRequest(uri);
       
   291         }
       
   292 
       
   293         System.out.println("**********************************");
       
   294         System.out.println("304 Not-Modified, (no content-length) ...");
       
   295         setResponse("304 Not-Modifed", -1);
       
   296         for (int i=0; i<5; i++) {
       
   297             actualTotal += doRequest(uri);
       
   298         }
       
   299 
       
   300         System.out.println("**********************************");
       
   301         System.out.println("204 No-Content, (no content-length) ...");
       
   302         setResponse("204 No-Content", -1);
       
   303         for (int i=0; i<5; i++) {
       
   304             actualTotal += doRequest(uri);
       
   305         }
       
   306 
       
   307         // shutdown server - we're done.
       
   308         svr.shutdown();
       
   309 
       
   310         System.out.println("**********************************");
       
   311 
       
   312         if (actualTotal == expectedTotal) {
       
   313             System.out.println("Passed: Actual total equal to expected total");
       
   314         } else {
       
   315             throw new Exception("Actual total != Expected total!!!");
       
   316         }
       
   317 
       
   318         int cnt = svr.connectionCount();
       
   319         if (cnt == 1) {
       
   320             System.out.println("Passed: Only 1 connection established");
       
   321         } else {
       
   322             throw new Exception("Test failed: Number of connections " +
       
   323                 "established: " + cnt + " - see log for details.");
       
   324         }
       
   325     }
       
   326 
       
   327     public static void main(String args[]) throws Exception {
       
   328 
       
   329         if (args.length > 0 && args[0].equals("-d")) {
       
   330             debug = true;
       
   331         }
       
   332 
       
   333         new ZeroContentLength();
       
   334     }
       
   335 
       
   336 }