1 /*
   2  * Copyright (c) 2015, 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 8068795
  27  * @summary The second space should not be omitted in first line(status-line) of
  28  * a http response message: http://tools.ietf.org/html/rfc7230#section-3.1.2 .
  29  * @author lev.priima@oracle.com
  30  */
  31 
  32 import java.net.InetSocketAddress;
  33 import java.io.InputStreamReader;
  34 import java.io.IOException;
  35 import java.io.BufferedReader;
  36 import java.io.OutputStreamWriter;
  37 import java.io.PrintWriter;
  38 import java.net.Socket;
  39 import java.util.concurrent.ExecutorService;
  40 import java.util.concurrent.Executors;
  41 import com.sun.net.httpserver.HttpExchange;
  42 import com.sun.net.httpserver.HttpHandler;
  43 import com.sun.net.httpserver.HttpServer;
  44 
  45 public class SpaceAtTheEndOfUnknownCodeStatusLineMsg {
  46 
  47     // this code is treated with unknown status-line msg in current HttpServer 
  48     // implementation:
  49     private static final int noMsgCode = 207; 
  50     private static final String someContext = "/context";
  51 
  52     public static void main(String[] args) throws Exception {
  53         HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
  54         try {
  55             server.setExecutor(Executors.newFixedThreadPool(1));
  56             server.createContext(someContext, new HttpHandler() {
  57                 @Override
  58                 public void handle(HttpExchange msg) {
  59                     try {
  60                         try {
  61                             msg.sendResponseHeaders(noMsgCode, -1);
  62                         } catch(IOException ioe) {
  63                             ioe.printStackTrace();
  64                         }
  65                     } finally {
  66                         msg.close();
  67                     }
  68                 }
  69             });
  70             server.start();
  71             System.out.println("Server started at port " 
  72                 + server.getAddress().getPort());
  73 
  74             runRawSocketHttpClient("localhost", server.getAddress().getPort());
  75         } finally {
  76             ((ExecutorService)server.getExecutor()).shutdown();
  77             server.stop(0);
  78         }
  79         System.out.println("Server finished.");
  80     }
  81 
  82     static void runRawSocketHttpClient(String hostname, int port ) 
  83             throws Exception {
  84         Socket socket = null;
  85         PrintWriter writer = null;
  86         BufferedReader reader = null;
  87         final String CRLF = "\r\n";
  88         try {
  89             socket = new Socket(hostname, port);
  90             writer = new PrintWriter(new OutputStreamWriter(
  91                 socket.getOutputStream()));
  92             System.out.println("Client connected by socket: " + socket);
  93 
  94             writer.print("GET " + someContext + "/ HTTP/1.1" + CRLF);
  95             writer.print("User-Agent: Java/" 
  96                 + System.getProperty("java.version")
  97                 + CRLF);
  98             writer.print("Host: " + hostname + CRLF);
  99             writer.print("Accept: */*" + CRLF);
 100             writer.print("Connection: keep-alive" + CRLF);
 101             writer.print(CRLF); // Important, else the server will expect that
 102             // there's more into the request.
 103             writer.flush();
 104             System.out.println("Client wrote rquest to socket: " + socket);
 105 
 106             reader = new BufferedReader(new InputStreamReader(
 107                 socket.getInputStream()));
 108             System.out.println("Client start reading from server:"  );
 109             String line = reader.readLine();
 110             if ( !line.endsWith(" ") ) {
 111                 throw new RuntimeException("respond to unknown code " 
 112                     + noMsgCode
 113                     + " doesn't return space at the end of the first header.\n"
 114                     + "Should be: " + "\"" + line + " \""
 115                     + ", but returns: " + "\"" + line + "\".");
 116             }
 117             for (; line != null; line = reader.readLine()) {
 118                 if (line.isEmpty()) {
 119                     break;
 120                 }
 121                 System.out.println("\""  + line + "\"");
 122             }
 123             System.out.println("Client finished reading from server"  );
 124         } finally {
 125             if (reader != null) 
 126                 try { 
 127                     reader.close(); 
 128                 } catch (IOException logOrIgnore) {
 129                     logOrIgnore.printStackTrace();
 130                 } 
 131             if (writer != null) { 
 132                 writer.close(); 
 133             }
 134             if (socket != null) {
 135                 try {
 136                     socket.close();
 137                 } catch (IOException logOrIgnore) {
 138                     logOrIgnore.printStackTrace();
 139                 }
 140             } 
 141         }
 142         System.out.println("Client finished." );
 143     }
 144 }
 145