/* * Copyright (c) 2018, 2022, 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 * @summary Verify that some special headers - such as User-Agent * can be specified by the caller. * @bug 8203771 8218546 8297200 * @modules java.base/sun.net.www.http * java.net.http/jdk.internal.net.http.common * java.net.http/jdk.internal.net.http.frame * java.net.http/jdk.internal.net.http.hpack * java.logging * jdk.httpserver * @library /test/lib http2/server * @build Http2TestServer HttpServerAdapters SpecialHeadersTest * @build jdk.test.lib.net.SimpleSSLContext * @run testng/othervm * -Djdk.httpclient.HttpClient.log=requests,headers,errors * SpecialHeadersTest * @run testng/othervm -Djdk.httpclient.allowRestrictedHeaders=Host * -Djdk.httpclient.HttpClient.log=requests,headers,errors * SpecialHeadersTest
*/
staticfinal String[][] headerNamesAndValues = new String[][]{
{"User-Agent: "},
{"User-Agent: camel-cased"},
{"user-agent: all-lower-case"},
{"user-Agent: mixed"}, // headers which were restricted before and are now allowable
{"referer: lower"},
{"Referer: normal"},
{"REFERER: upper"},
{"origin: lower"},
{"Origin: normal"},
{"ORIGIN: upper"},
};
// Needs net.property enabled for this part of test staticfinal String[][] headerNamesAndValues1 = new String[][]{
{"Host: "},
{"Host: camel-cased"},
{"host: all-lower-case"},
{"hoSt: mixed"}
};
for (boolean sameClient : newboolean[] { false, true }) {
Arrays.asList(testInput).stream()
.map(e -> new Object[] {httpURI, e[0], sameClient})
.forEach(list::add);
Arrays.asList(testInput).stream()
.map(e -> new Object[] {httpsURI, e[0], sameClient})
.forEach(list::add);
Arrays.asList(testInput).stream()
.map(e -> new Object[] {http2URI, e[0], sameClient})
.forEach(list::add);
Arrays.asList(testInput).stream()
.map(e -> new Object[] {https2URI, e[0], sameClient})
.forEach(list::add);
} return list.stream().toArray(Object[][]::new);
}
staticfinalint ITERATION_COUNT = 3; // checks upgrade and re-use // a shared executor helps reduce the amount of threads created by the test staticfinal TestExecutor executor = new TestExecutor(Executors.newCachedThreadPool()); staticfinal ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>(); staticvolatileboolean tasksFailed; staticfinal AtomicLong serverCount = new AtomicLong(); staticfinal AtomicLong clientCount = new AtomicLong(); staticfinallong start = System.nanoTime(); publicstatic String now() { long now = System.nanoTime() - start; long secs = now / 1000_000_000; long mill = (now % 1000_000_000) / 1000_000; long nan = now % 1000_000; return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
}
final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; privatevolatile HttpClient sharedClient;
staticclass TestExecutor implements Executor { final AtomicLong tasks = new AtomicLong();
Executor executor;
TestExecutor(Executor executor) { this.executor = executor;
}
staticvolatile String lastMethod;
HttpClient newHttpClient(String method, boolean share) { if (!share) return TRACKER.track(makeNewClient());
HttpClient shared = sharedClient;
String last = lastMethod; if (shared != null && Objects.equals(last, method)) return shared; synchronized (this) {
shared = sharedClient;
last = lastMethod; if (!Objects.equals(last, method)) { // reset sharedClient to avoid side effects // between methods. This is needed to keep the test // expectation that the first HTTP/2 clear request // will be an upgrade if (shared != null) {
TRACKER.track(shared);
shared = sharedClient = null;
}
} if (shared == null) {
shared = sharedClient = makeNewClient();
last = lastMethod = method;
} return shared;
}
}
// By default, HTTP/2 sets the `:authority:` pseudo-header, instead // of the `Host` header. Therefore, there should be no "X-Host" // header in the response, except the response to the h2c Upgrade // request which will have been sent through HTTP/1.1.
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(response -> {
out.println("Got response: " + response);
out.println("Got body: " + response.body());
assertEquals(response.statusCode(), 200); return response;
})
.thenAccept(resp -> { // By default, HTTP/2 sets the `:authority:` pseudo-header, instead // of the `Host` header. Therefore, there should be no "X-Host" // header in the response, except the response to the h2c Upgrade // request which will have been sent through HTTP/1.1.
/** A handler that returns, as its body, the exact received request URI. * The header whose name is in the URI query and is set in the request is * returned in the response with its name prefixed by X-
*/ staticclass HttpUriStringHandler implements HttpTestHandler {
@Override publicvoid handle(HttpTestExchange t) throws IOException {
URI uri = t.getRequestURI();
String uriString = uri.toString();
out.println("HttpUriStringHandler received, uri: " + uriString);
String query = uri.getQuery();
String headerName = query.substring(query.indexOf("=")+1).trim();
out.println("HttpUriStringHandler received, headerName: " + headerName
+ "\n\theaders: " + t.getRequestHeaders()); try (InputStream is = t.getRequestBody();
OutputStream os = t.getResponseBody()) {
is.readAllBytes(); byte[] bytes = uriString.getBytes(US_ASCII);
t.getRequestHeaders().keySet().stream()
.filter(headerName::equalsIgnoreCase)
.forEach(h -> { for (String v : t.getRequestHeaders().get(headerName)) {
t.getResponseHeaders().addHeader("X-"+h, v);
}
});
t.sendResponseHeaders(200, bytes.length);
os.write(bytes);
}
}
}
}
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.