Skip to content

Commit 5973e91

Browse files
committed
8253005: Add @throws IOException in javadoc for HttpEchange.sendResponseHeaders
Reviewed-by: dfuchs
1 parent 8c31bd2 commit 5973e91

File tree

2 files changed

+126
-3
lines changed

2 files changed

+126
-3
lines changed

src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.io.OutputStream;
3131
import java.net.InetSocketAddress;
3232
import java.net.URI;
33+
import java.util.Map;
3334

3435
/**
3536
* This class encapsulates a HTTP request received and a
@@ -163,7 +164,7 @@ protected HttpExchange() {
163164
* <p> If the call to {@link #sendResponseHeaders(int, long)} specified a
164165
* fixed response body length, then the exact number of bytes specified in
165166
* that call must be written to this stream. If too many bytes are written,
166-
* then {@link OutputStream#write()} will throw an {@code IOException}.
167+
* then the write method of {@link OutputStream} will throw an {@code IOException}.
167168
* If too few bytes are written then the stream
168169
* {@link OutputStream#close()} will throw an {@code IOException}.
169170
* In both cases, the exchange is aborted and the underlying TCP connection
@@ -207,7 +208,7 @@ protected HttpExchange() {
207208
* and an arbitrary number of bytes may be written.
208209
* If {@literal <= -1}, then no response body length is
209210
* specified and no response body may be written.
210-
*
211+
* @throws IOException if the response headers have already been sent or an I/O error occurs
211212
* @see HttpExchange#getResponseBody()
212213
*/
213214
public abstract void sendResponseHeaders(int rCode, long responseLength) throws IOException;
@@ -243,7 +244,7 @@ protected HttpExchange() {
243244
public abstract String getProtocol();
244245

245246
/**
246-
* {@Link Filter} modules may store arbitrary objects with {@code HttpExchange}
247+
* {@link Filter} modules may store arbitrary objects with {@code HttpExchange}
247248
* instances as an out-of-band communication mechanism. Other filters
248249
* or the exchange handler may then access these objects.
249250
*
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (c) 2020, 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 8253005
27+
* @library /test/lib
28+
* @summary Check that sendResponseHeaders throws an IOException when headers
29+
* have already been sent
30+
* @run testng/othervm SendResponseHeadersTest
31+
*/
32+
33+
import com.sun.net.httpserver.HttpExchange;
34+
import com.sun.net.httpserver.HttpHandler;
35+
import com.sun.net.httpserver.HttpServer;
36+
import jdk.test.lib.net.URIBuilder;
37+
import org.testng.annotations.AfterTest;
38+
import org.testng.annotations.BeforeTest;
39+
import org.testng.annotations.Test;
40+
41+
import java.io.IOException;
42+
import java.io.InputStream;
43+
import java.io.OutputStream;
44+
import java.net.InetAddress;
45+
import java.net.InetSocketAddress;
46+
import java.net.URI;
47+
import java.net.URISyntaxException;
48+
import java.net.http.HttpClient;
49+
import java.net.http.HttpRequest;
50+
import java.net.http.HttpResponse;
51+
import java.net.http.HttpResponse.BodyHandlers;
52+
import java.nio.charset.StandardCharsets;
53+
import java.util.concurrent.ExecutorService;
54+
import java.util.concurrent.Executors;
55+
56+
import static java.net.http.HttpClient.Builder.NO_PROXY;
57+
import static org.testng.Assert.expectThrows;
58+
import static org.testng.Assert.fail;
59+
60+
public class SendResponseHeadersTest {
61+
URI uri;
62+
HttpServer server;
63+
ExecutorService executor;
64+
65+
@BeforeTest
66+
public void setUp() throws IOException, URISyntaxException {
67+
var loopback = InetAddress.getLoopbackAddress();
68+
var addr = new InetSocketAddress(loopback, 0);
69+
server = HttpServer.create(addr, 0);
70+
server.createContext("/test", new TestHandler());
71+
executor = Executors.newCachedThreadPool();
72+
server.setExecutor(executor);
73+
server.start();
74+
75+
uri = URIBuilder.newBuilder()
76+
.scheme("http")
77+
.host(loopback)
78+
.port(server.getAddress().getPort())
79+
.path("/test/foo.html")
80+
.build();
81+
}
82+
83+
@Test
84+
public void testSend() throws Exception {
85+
HttpClient client = HttpClient.newBuilder()
86+
.proxy(NO_PROXY)
87+
.build();
88+
HttpRequest request = HttpRequest.newBuilder(uri)
89+
.GET()
90+
.build();
91+
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
92+
// verify empty response received, otherwise an error has occurred
93+
if (!response.body().isEmpty())
94+
fail(response.body());
95+
}
96+
97+
@AfterTest
98+
public void tearDown() {
99+
server.stop(0);
100+
executor.shutdown();
101+
}
102+
103+
static class TestHandler implements HttpHandler {
104+
public void handle(HttpExchange exchange) throws IOException {
105+
try (InputStream is = exchange.getRequestBody();
106+
OutputStream os = exchange.getResponseBody()) {
107+
108+
is.readAllBytes();
109+
exchange.sendResponseHeaders(200, 0);
110+
try {
111+
IOException io = expectThrows(IOException.class,
112+
() -> exchange.sendResponseHeaders(200, 0));
113+
System.out.println("Got expected exception: " + io);
114+
} catch (Throwable t) {
115+
// expectThrows triggered an assertion, return error message to the client
116+
t.printStackTrace();
117+
os.write(("Unexpected error: " + t).getBytes(StandardCharsets.UTF_8));
118+
}
119+
}
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)