undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
312
test/jdk/java/net/httpclient/http2/ServerPush.java
Normal file
312
test/jdk/java/net/httpclient/http2/ServerPush.java
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8087112 8159814
|
||||
* @library /test/jdk/java/net/httpclient/lib
|
||||
* /test/lib
|
||||
* @build jdk.httpclient.test.lib.http2.Http2TestServer
|
||||
* jdk.httpclient.test.lib.http2.PushHandler
|
||||
* jdk.test.lib.Utils
|
||||
* @run junit/othervm
|
||||
* -Djdk.httpclient.HttpClient.log=errors,requests,responses
|
||||
* ServerPush
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.*;
|
||||
import java.net.http.*;
|
||||
import java.net.http.HttpResponse.BodyHandler;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.net.http.HttpResponse.BodySubscribers;
|
||||
import java.net.http.HttpResponse.PushPromiseHandler;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
import jdk.httpclient.test.lib.http2.Http2TestServer;
|
||||
import jdk.httpclient.test.lib.http2.PushHandler;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static jdk.test.lib.Utils.createTempFileOfSize;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ServerPush {
|
||||
|
||||
private static final String TEMP_FILE_PREFIX =
|
||||
HttpClient.class.getPackageName() + '-' + ServerPush.class.getSimpleName() + '-';
|
||||
|
||||
static final int LOOPS = 13;
|
||||
static final int FILE_SIZE = 512 * 1024 + 343;
|
||||
|
||||
static Path tempFile;
|
||||
|
||||
private static Http2TestServer server;
|
||||
private static URI uri;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws Exception {
|
||||
tempFile = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILE_SIZE);
|
||||
server = new Http2TestServer(false, 0);
|
||||
server.addHandler(new PushHandler(tempFile, LOOPS), "/");
|
||||
System.out.println("Using temp file:" + tempFile);
|
||||
|
||||
System.err.println("Server listening on port " + server.getAddress().getPort());
|
||||
server.start();
|
||||
int port = server.getAddress().getPort();
|
||||
uri = new URI("http://localhost:" + port + "/foo/a/b/c");
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void teardown() {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
// Test 1 - custom written push promise handler, everything as a String
|
||||
@Test
|
||||
public void testTypeString() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>>
|
||||
resultMap = new ConcurrentHashMap<>();
|
||||
|
||||
PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> {
|
||||
BodyHandler<String> s = BodyHandlers.ofString(UTF_8);
|
||||
CompletableFuture<HttpResponse<String>> cf = acceptor.apply(s);
|
||||
resultMap.put(pushRequest, cf);
|
||||
};
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
CompletableFuture<HttpResponse<String>> cf =
|
||||
client.sendAsync(request, BodyHandlers.ofString(UTF_8), pph);
|
||||
cf.join();
|
||||
resultMap.put(request, cf);
|
||||
System.err.println("results.size: " + resultMap.size());
|
||||
for (HttpRequest r : resultMap.keySet()) {
|
||||
HttpResponse<String> response = resultMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
assertEquals(tempFileAsString, response.body());
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultMap.size());
|
||||
}
|
||||
|
||||
// Test 2 - of(...) populating the given Map, everything as a String
|
||||
@Test
|
||||
public void testTypeStringOfMap() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>>
|
||||
resultMap = new ConcurrentHashMap<>();
|
||||
|
||||
PushPromiseHandler<String> pph =
|
||||
PushPromiseHandler.of(pushPromise -> BodyHandlers.ofString(UTF_8),
|
||||
resultMap);
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
CompletableFuture<HttpResponse<String>> cf =
|
||||
client.sendAsync(request, BodyHandlers.ofString(UTF_8), pph);
|
||||
cf.join();
|
||||
resultMap.put(request, cf);
|
||||
System.err.println("results.size: " + resultMap.size());
|
||||
for (HttpRequest r : resultMap.keySet()) {
|
||||
HttpResponse<String> response = resultMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
assertEquals(tempFileAsString, response.body());
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultMap.size());
|
||||
}
|
||||
|
||||
// --- Path ---
|
||||
|
||||
static final Path dir = Paths.get(".", "serverPush");
|
||||
static BodyHandler<Path> requestToPath(HttpRequest req) {
|
||||
URI u = req.uri();
|
||||
Path path = Paths.get(dir.toString(), u.getPath());
|
||||
try {
|
||||
Files.createDirectories(path.getParent());
|
||||
} catch (IOException ee) {
|
||||
throw new UncheckedIOException(ee);
|
||||
}
|
||||
return BodyHandlers.ofFile(path);
|
||||
}
|
||||
|
||||
// Test 3 - custom written push promise handler, everything as a Path
|
||||
@Test
|
||||
public void testTypePath() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
PushPromiseHandler<Path> pushPromiseHandler = (initial, pushRequest, acceptor) -> {
|
||||
BodyHandler<Path> pp = requestToPath(pushRequest);
|
||||
CompletableFuture<HttpResponse<Path>> cf = acceptor.apply(pp);
|
||||
resultsMap.put(pushRequest, cf);
|
||||
};
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
CompletableFuture<HttpResponse<Path>> cf =
|
||||
client.sendAsync(request, requestToPath(request), pushPromiseHandler);
|
||||
cf.join();
|
||||
resultsMap.put(request, cf);
|
||||
|
||||
for (HttpRequest r : resultsMap.keySet()) {
|
||||
HttpResponse<Path> response = resultsMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8);
|
||||
assertEquals(tempFileAsString, fileAsString);
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultsMap.size());
|
||||
}
|
||||
|
||||
// Test 4 - of(...) populating the given Map, everything as a Path
|
||||
@Test
|
||||
public void testTypePathOfMap() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Path>>> resultsMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
PushPromiseHandler<Path> pushPromiseHandler =
|
||||
PushPromiseHandler.of(pushRequest -> requestToPath(pushRequest),
|
||||
resultsMap);
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
CompletableFuture<HttpResponse<Path>> cf =
|
||||
client.sendAsync(request, requestToPath(request), pushPromiseHandler);
|
||||
cf.join();
|
||||
resultsMap.put(request, cf);
|
||||
|
||||
for (HttpRequest r : resultsMap.keySet()) {
|
||||
HttpResponse<Path> response = resultsMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8);
|
||||
assertEquals(tempFileAsString, fileAsString);
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultsMap.size());
|
||||
}
|
||||
|
||||
// --- Consumer<byte[]> ---
|
||||
|
||||
static class ByteArrayConsumer implements Consumer<Optional<byte[]>> {
|
||||
volatile List<byte[]> listByteArrays = new ArrayList<>();
|
||||
volatile byte[] accumulatedBytes;
|
||||
|
||||
public byte[] getAccumulatedBytes() { return accumulatedBytes; }
|
||||
|
||||
@Override
|
||||
public void accept(Optional<byte[]> optionalBytes) {
|
||||
assert accumulatedBytes == null;
|
||||
if (!optionalBytes.isPresent()) {
|
||||
int size = listByteArrays.stream().mapToInt(ba -> ba.length).sum();
|
||||
ByteBuffer bb = ByteBuffer.allocate(size);
|
||||
listByteArrays.stream().forEach(ba -> bb.put(ba));
|
||||
accumulatedBytes = bb.array();
|
||||
} else {
|
||||
listByteArrays.add(optionalBytes.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test 5 - custom written handler, everything as a consumer of optional byte[]
|
||||
@Test
|
||||
public void testTypeByteArrayConsumer() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap
|
||||
= new ConcurrentHashMap<>();
|
||||
Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
ByteArrayConsumer bac = new ByteArrayConsumer();
|
||||
byteArrayConsumerMap.put(request, bac);
|
||||
|
||||
PushPromiseHandler<Void> pushPromiseHandler = (initial, pushRequest, acceptor) -> {
|
||||
CompletableFuture<HttpResponse<Void>> cf = acceptor.apply(
|
||||
(info) -> {
|
||||
ByteArrayConsumer bc = new ByteArrayConsumer();
|
||||
byteArrayConsumerMap.put(pushRequest, bc);
|
||||
return BodySubscribers.ofByteArrayConsumer(bc); } );
|
||||
resultsMap.put(pushRequest, cf);
|
||||
};
|
||||
|
||||
CompletableFuture<HttpResponse<Void>> cf =
|
||||
client.sendAsync(request, BodyHandlers.ofByteArrayConsumer(bac), pushPromiseHandler);
|
||||
cf.join();
|
||||
resultsMap.put(request, cf);
|
||||
|
||||
for (HttpRequest r : resultsMap.keySet()) {
|
||||
HttpResponse<Void> response = resultsMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes();
|
||||
String result = new String(ba, UTF_8);
|
||||
assertEquals(tempFileAsString, result);
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultsMap.size());
|
||||
}
|
||||
|
||||
// Test 6 - of(...) populating the given Map, everything as a consumer of optional byte[]
|
||||
@Test
|
||||
public void testTypeByteArrayConsumerOfMap() throws Exception {
|
||||
String tempFileAsString = new String(Files.readAllBytes(tempFile), UTF_8);
|
||||
ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<Void>>> resultsMap
|
||||
= new ConcurrentHashMap<>();
|
||||
Map<HttpRequest,ByteArrayConsumer> byteArrayConsumerMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
|
||||
ByteArrayConsumer bac = new ByteArrayConsumer();
|
||||
byteArrayConsumerMap.put(request, bac);
|
||||
|
||||
PushPromiseHandler<Void> pushPromiseHandler =
|
||||
PushPromiseHandler.of(
|
||||
pushRequest -> {
|
||||
ByteArrayConsumer bc = new ByteArrayConsumer();
|
||||
byteArrayConsumerMap.put(pushRequest, bc);
|
||||
return BodyHandlers.ofByteArrayConsumer(bc);
|
||||
},
|
||||
resultsMap);
|
||||
|
||||
CompletableFuture<HttpResponse<Void>> cf =
|
||||
client.sendAsync(request, BodyHandlers.ofByteArrayConsumer(bac), pushPromiseHandler);
|
||||
cf.join();
|
||||
resultsMap.put(request, cf);
|
||||
|
||||
for (HttpRequest r : resultsMap.keySet()) {
|
||||
HttpResponse<Void> response = resultsMap.get(r).join();
|
||||
assertEquals(200, response.statusCode());
|
||||
byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes();
|
||||
String result = new String(ba, UTF_8);
|
||||
assertEquals(tempFileAsString, result);
|
||||
}
|
||||
assertEquals(LOOPS + 1, resultsMap.size());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue