/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/java/net/httpclient/http3/H3BadHeadersTest.java
329 строк
14 KB
Daisuke Yamazaki
8372325: Refactor tests under jdk/java/net/httpclient to use ${test.main.class}
09 апр 2026, 13:51
09 апр 2026, 13:51
261011a
Код
Авторство
О чём код?
/* * Copyright (c) 2018, 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 * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.test.lib.net.SimpleSSLContext * @compile ../ReferenceTracker.java * @run junit/othervm -Djdk.internal.httpclient.debug=true ${test.main.class} * @summary this test verifies the behaviour of the HttpClient when presented * with bad headers */ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.util.List.of; import static java.util.Map.entry; import org.junit.jupiter.api.AfterAll; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; public class H3BadHeadersTest implements HttpServerAdapters { private static final List<List<Entry<String, String>>> BAD_HEADERS = of( of(entry(":status", "200"), entry(":hello", "GET")), // Unknown pseudo-header of(entry(":status", "200"), entry("hell o", "value")), // Space in the name of(entry(":status", "200"), entry("hello", "line1\r\n line2\r\n")), // Multiline value of(entry(":status", "200"), entry("hello", "DE" + ((char) 0x7F) + "L")) // Bad byte in value // Not easily testable with H3, because we use a HttpHeadersBuilders which sorts headers... // of(entry("hello", "world!"), entry(":status", "200")) // Pseudo header is not the first one ); static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); private static HttpTestServer http3TestServer; // HTTP/3 ( h3 only ) private static HttpTestServer https2TestServer; // HTTP/2 ( h2 + h3 ) private static String http3URI; private static String https2URI; public static Object[][] variants() { return new Object[][] { { http3URI, false}, { https2URI, false}, { http3URI, true}, { https2URI, true}, }; } @ParameterizedTest @MethodSource("variants") void test(String uri, boolean sameClient) throws Exception { System.out.printf("%ntest %s, %s, STARTING%n%n", uri, sameClient); System.err.printf("%ntest %s, %s, STARTING%n%n", uri, sameClient); var config = uri.startsWith(http3URI) ? Http3DiscoveryMode.HTTP_3_URI_ONLY : https2TestServer.supportsH3DirectConnection() ? Http3DiscoveryMode.ANY : Http3DiscoveryMode.ALT_SVC; boolean sendHeadRequest = config != Http3DiscoveryMode.HTTP_3_URI_ONLY; HttpClient client = null; for (int i=0; i< BAD_HEADERS.size(); i++) { boolean needsHeadRequest = false; if (!sameClient || client == null) { needsHeadRequest = sendHeadRequest; client = newClientBuilderForH3() .version(Version.HTTP_3) .sslContext(sslContext) .build(); } if (needsHeadRequest) { URI simpleURI = URI.create(uri); HttpRequest head = HttpRequest.newBuilder(simpleURI) .version(Version.HTTP_2) .HEAD().setOption(H3_DISCOVERY, config).build(); System.out.println("\nSending HEAD request: " + head); var headResponse = client.send(head, BodyHandlers.ofString()); assertEquals(200, headResponse.statusCode()); assertEquals(Version.HTTP_2, headResponse.version()); } URI uriWithQuery = URI.create(uri + "?BAD_HEADERS=" + i); HttpRequest request = HttpRequest.newBuilder(uriWithQuery) .POST(BodyPublishers.ofString("Hello there!")) .setOption(H3_DISCOVERY, config) .version(Version.HTTP_3) .build(); System.out.println("\nSending request:" + uriWithQuery); try { HttpResponse<String> response = client.send(request, BodyHandlers.ofString()); fail("Expected exception, got :" + response + ", " + response.body()); } catch (IOException ioe) { System.out.println("Got EXPECTED: " + ioe); assertDetailMessage(ioe, i); } if (!sameClient) { var tracker = TRACKER.getTracker(client); client = null; System.gc(); var error = TRACKER.check(tracker, 1500); if (error != null) throw error; } } if (client != null) { var tracker = TRACKER.getTracker(client); client = null; System.gc(); var error = TRACKER.check(tracker, 1500); if (error != null) throw error; } System.out.printf("%ntest %s, %s, DONE%n%n", uri, sameClient); System.err.printf("%ntest %s, %s, DONE%n%n", uri, sameClient); } @ParameterizedTest @MethodSource("variants") void testAsync(String uri, boolean sameClient) throws Exception { System.out.printf("%ntestAsync %s, %s, STARTING%n%n", uri, sameClient); System.err.printf("%ntestAsync %s, %s, STARTING%n%n", uri, sameClient); var config = uri.startsWith(http3URI) ? Http3DiscoveryMode.HTTP_3_URI_ONLY : https2TestServer.supportsH3DirectConnection() ? Http3DiscoveryMode.ANY : Http3DiscoveryMode.ALT_SVC; boolean sendHeadRequest = config != Http3DiscoveryMode.HTTP_3_URI_ONLY; HttpClient client = null; for (int i=0; i< BAD_HEADERS.size(); i++) { boolean needsHeadRequest = false; if (!sameClient || client == null) { needsHeadRequest = sendHeadRequest; client = newClientBuilderForH3() .version(Version.HTTP_3) .sslContext(sslContext) .build(); } if (needsHeadRequest) { URI simpleURI = URI.create(uri); HttpRequest head = HttpRequest.newBuilder(simpleURI) .version(Version.HTTP_2) .HEAD() .setOption(H3_DISCOVERY, config) .build(); System.out.println("\nSending HEAD request: " + head); var headResponse = client.send(head, BodyHandlers.ofString()); assertEquals(200, headResponse.statusCode()); assertEquals(Version.HTTP_2, headResponse.version()); } URI uriWithQuery = URI.create(uri + "?BAD_HEADERS=" + i); HttpRequest request = HttpRequest.newBuilder(uriWithQuery) .POST(BodyPublishers.ofString("Hello there!")) .setOption(H3_DISCOVERY, config) .version(Version.HTTP_3) .build(); System.out.println("\nSending request:" + uriWithQuery); Throwable t = null; try { HttpResponse<String> response = client.sendAsync(request, BodyHandlers.ofString()).get(); fail("Expected exception, got :" + response + ", " + response.body()); } catch (Throwable t0) { System.out.println("Got EXPECTED: " + t0); if (t0 instanceof ExecutionException) { t0 = t0.getCause(); } t = t0; } assertDetailMessage(t, i); if (!sameClient) { var tracker = TRACKER.getTracker(client); client = null; System.gc(); var error = TRACKER.check(tracker, 1500); if (error != null) throw error; } } if (client != null) { var tracker = TRACKER.getTracker(client); client = null; System.gc(); var error = TRACKER.check(tracker, 1500); if (error != null) throw error; } System.out.printf("%ntestAsync %s, %s, DONE%n%n", uri, sameClient); System.err.printf("%ntestAsync %s, %s, DONE%n%n", uri, sameClient); } // Assertions based on implementation specific detail messages. Keep in // sync with implementation. static void assertDetailMessage(Throwable throwable, int iterationIndex) { try { assertInstanceOf(IOException.class, throwable, "Expected IOException, got, " + throwable); assertNotNull(throwable.getMessage(), "No message for " + throwable); assertTrue(throwable.getMessage().contains("malformed response"), "Expected \"malformed response\" in: " + throwable.getMessage()); if (iterationIndex == 0) { // unknown assertTrue(throwable.getMessage().contains("Unknown pseudo-header"), "Expected \"Unknown pseudo-header\" in: " + throwable.getMessage()); } else if (iterationIndex == 4) { // unexpected assertTrue(throwable.getMessage().contains(" Unexpected pseudo-header"), "Expected \" Unexpected pseudo-header\" in: " + throwable.getMessage()); } else { assertTrue(throwable.getMessage().contains("Bad header"), "Expected \"Bad header\" in: " + throwable.getMessage()); } } catch (AssertionError e) { System.out.println("Exception does not match expectation: " + throwable); throwable.printStackTrace(System.out); throw e; } } @BeforeAll public static void setup() throws Exception { System.out.println("creating servers"); http3TestServer = HttpTestServer.create(Http3DiscoveryMode.HTTP_3_URI_ONLY, sslContext); http3TestServer.addHandler(new BadHeadersHandler(), "/http3/echo"); http3URI = "https://" + http3TestServer.serverAuthority() + "/http3/echo"; https2TestServer = HttpTestServer.create(Http3DiscoveryMode.ANY, sslContext); https2TestServer.addHandler(new BadHeadersHandler(), "/https2/echo"); https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo"; http3TestServer.start(); https2TestServer.start(); System.out.println("server started"); } @AfterAll public static void teardown() throws Exception { System.err.println("\n\n**** stopping servers\n"); System.out.println("stopping servers"); http3TestServer.stop(); https2TestServer.stop(); System.out.println("servers stopped"); } static class BadHeadersHandler implements HttpTestHandler { @Override public void handle(HttpTestExchange t) throws IOException { var uri = t.getRequestURI(); String query = uri.getRawQuery(); if (query != null && !query.isEmpty()) { int badHeadersIndex = Integer.parseInt(query.substring(query.indexOf("=") + 1)); assert badHeadersIndex >= 0 && badHeadersIndex < BAD_HEADERS.size() : "Unexpected badHeadersIndex value: " + badHeadersIndex; List<Entry<String, String>> headers = BAD_HEADERS.get(badHeadersIndex); var responseHeaders = t.getResponseHeaders(); for (var e : headers) { responseHeaders.addHeader(e.getKey(), e.getValue()); } } try (InputStream is = t.getRequestBody(); OutputStream os = t.getResponseBody()) { byte[] bytes = is.readAllBytes(); t.sendResponseHeaders(200, bytes.length); if (t.getRequestMethod().equals("HEAD")) { os.close(); } else { os.write(bytes); } } } } }