1 /*
2  * Copyright (c) 2015, 2018, 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 8087112
27  * @library /lib/testlibrary/ server
28  * @build jdk.testlibrary.SimpleSSLContext
29  * @modules java.base/sun.net.www.http
30  *          java.net.http/jdk.internal.net.http.common
31  *          java.net.http/jdk.internal.net.http.frame
32  *          java.net.http/jdk.internal.net.http.hpack
33  * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors NoBodyTest
34  */
35 
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.net.*;
40 import javax.net.ssl.*;
41 import java.net.http.HttpClient;
42 import java.net.http.HttpHeaders;
43 import java.net.http.HttpRequest;
44 import java.net.http.HttpRequest.BodyPublishers;
45 import java.net.http.HttpResponse;
46 import java.net.http.HttpResponse.BodyHandlers;
47 import java.util.concurrent.*;
48 import jdk.testlibrary.SimpleSSLContext;
49 import org.testng.annotations.Test;
50 import static java.net.http.HttpClient.Version.HTTP_2;
51 
52 @Test
53 public class NoBodyTest {
54     static int httpPort, httpsPort;
55     static Http2TestServer httpServer, httpsServer;
56     static HttpClient client = null;
57     static ExecutorService clientExec;
58     static ExecutorService serverExec;
59     static SSLContext sslContext;
60     static String TEST_STRING = "The quick brown fox jumps over the lazy dog ";
61 
62     static String httpURIString, httpsURIString;
63 
initialize()64     static void initialize() throws Exception {
65         try {
66             SimpleSSLContext sslct = new SimpleSSLContext();
67             sslContext = sslct.get();
68             client = getClient();
69             httpServer = new Http2TestServer(false, 0, serverExec, sslContext);
70             httpServer.addHandler(new Handler(), "/");
71             httpPort = httpServer.getAddress().getPort();
72 
73             httpsServer = new Http2TestServer(true, 0, serverExec, sslContext);
74             httpsServer.addHandler(new Handler(), "/");
75 
76             httpsPort = httpsServer.getAddress().getPort();
77             httpURIString = "http://localhost:" + httpPort + "/foo/";
78             httpsURIString = "https://localhost:" + httpsPort + "/bar/";
79 
80             httpServer.start();
81             httpsServer.start();
82         } catch (Throwable e) {
83             System.err.println("Throwing now");
84             e.printStackTrace(System.err);
85             throw e;
86         }
87     }
88 
89     @Test
runtest()90     public static void runtest() throws Exception {
91         try {
92             initialize();
93             warmup(false);
94             warmup(true);
95             test(false);
96             test(true);
97         } catch (Throwable tt) {
98             System.err.println("tt caught");
99             tt.printStackTrace(System.err);
100             throw tt;
101         } finally {
102             httpServer.stop();
103             httpsServer.stop();
104         }
105     }
106 
getClient()107     static HttpClient getClient() {
108         if (client == null) {
109             serverExec = Executors.newCachedThreadPool();
110             clientExec = Executors.newCachedThreadPool();
111             client = HttpClient.newBuilder()
112                                .executor(clientExec)
113                                .sslContext(sslContext)
114                                .version(HTTP_2)
115                                .build();
116         }
117         return client;
118     }
119 
getURI(boolean secure)120     static URI getURI(boolean secure) {
121         if (secure)
122             return URI.create(httpsURIString);
123         else
124             return URI.create(httpURIString);
125     }
126 
checkStatus(int expected, int found)127     static void checkStatus(int expected, int found) throws Exception {
128         if (expected != found) {
129             System.err.printf ("Test failed: wrong status code %d/%d\n",
130                 expected, found);
131             throw new RuntimeException("Test failed");
132         }
133     }
134 
checkStrings(String expected, String found)135     static void checkStrings(String expected, String found) throws Exception {
136         if (!expected.equals(found)) {
137             System.err.printf ("Test failed: wrong string %s/%s\n",
138                 expected, found);
139             throw new RuntimeException("Test failed");
140         }
141     }
142 
143     static final int LOOPS = 13;
144 
warmup(boolean secure)145     static void warmup(boolean secure) throws Exception {
146         URI uri = getURI(secure);
147         String type = secure ? "https" : "http";
148         System.err.println("Request to " + uri);
149 
150         // Do a simple warmup request
151 
152         HttpClient client = getClient();
153         HttpRequest req = HttpRequest.newBuilder(uri)
154                                      .POST(BodyPublishers.ofString("Random text"))
155                                      .build();
156         HttpResponse<String> response = client.send(req, BodyHandlers.ofString());
157         checkStatus(200, response.statusCode());
158         String responseBody = response.body();
159         HttpHeaders h = response.headers();
160         checkStrings(TEST_STRING + type, responseBody);
161     }
162 
test(boolean secure)163     static void test(boolean secure) throws Exception {
164         URI uri = getURI(secure);
165         String type = secure ? "https" : "http";
166         System.err.println("Request to " + uri);
167 
168         HttpRequest request = HttpRequest.newBuilder(uri)
169                 .POST(BodyPublishers.ofString(TEST_STRING))
170                 .build();
171         for (int i = 0; i < LOOPS; i++) {
172             System.out.println("Loop " + i);
173             HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
174             int expectedResponse = (i % 2) == 0 ? 204 : 200;
175             if (response.statusCode() != expectedResponse)
176                 throw new RuntimeException("wrong response code " + Integer.toString(response.statusCode()));
177             if (expectedResponse == 200 && !response.body().equals(TEST_STRING + type)) {
178                 System.err.printf("response received/expected %s/%s\n", response.body(), TEST_STRING + type);
179                 throw new RuntimeException("wrong response body");
180             }
181         }
182         System.err.println("test: DONE");
183     }
184 
185     static class Handler implements Http2Handler {
186 
Handler()187         public Handler() {}
188 
189         volatile int invocation = 0;
190 
191         @Override
handle(Http2TestExchange t)192         public void handle(Http2TestExchange t)
193                 throws IOException {
194             try {
195                 URI uri = t.getRequestURI();
196                 System.err.printf("Handler received request to %s from %s\n",
197                         uri, t.getRemoteAddress());
198                 String type = uri.getScheme().toLowerCase();
199                 InputStream is = t.getRequestBody();
200                 while (is.read() != -1);
201                 is.close();
202 
203                 // every second response is 204.
204 
205                 if ((invocation++ % 2) == 1) {
206                     System.err.println("Server sending 204");
207                     t.sendResponseHeaders(204, -1);
208                 } else {
209                     String body = TEST_STRING + type;
210                     t.sendResponseHeaders(200, body.length());
211                     OutputStream os = t.getResponseBody();
212                     os.write(body.getBytes());
213                     os.close();
214                 }
215             } catch (Throwable e) {
216                 e.printStackTrace(System.err);
217                 throw new IOException(e);
218             }
219         }
220     }
221 }
222