|
1 | 1 | /* |
2 | | - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
|
25 | 25 | * @test |
26 | 26 | * @summary Verify that some special headers - such as User-Agent |
27 | 27 | * can be specified by the caller. |
28 | | - * @bug 8203771 |
| 28 | + * @bug 8203771 8218546 |
29 | 29 | * @modules java.base/sun.net.www.http |
30 | 30 | * java.net.http/jdk.internal.net.http.common |
31 | 31 | * java.net.http/jdk.internal.net.http.frame |
|
64 | 64 | import java.net.http.HttpRequest; |
65 | 65 | import java.net.http.HttpResponse; |
66 | 66 | import java.net.http.HttpResponse.BodyHandlers; |
67 | | -import java.security.AccessController; |
68 | | -import java.security.PrivilegedAction; |
69 | 67 | import java.time.Duration; |
70 | 68 | import java.util.ArrayList; |
71 | 69 | import java.util.Arrays; |
|
74 | 72 | import java.util.Map; |
75 | 73 | import java.util.Optional; |
76 | 74 | import java.util.function.Function; |
77 | | - |
78 | | -import static java.lang.System.err; |
79 | 75 | import static java.lang.System.out; |
80 | 76 | import static java.net.http.HttpClient.Builder.NO_PROXY; |
| 77 | +import static java.net.http.HttpClient.Version.HTTP_2; |
81 | 78 | import static java.nio.charset.StandardCharsets.US_ASCII; |
82 | 79 | import org.testng.Assert; |
83 | 80 | import static org.testng.Assert.assertEquals; |
| 81 | +import static org.testng.Assert.assertTrue; |
84 | 82 |
|
85 | 83 | public class SpecialHeadersTest implements HttpServerAdapters { |
86 | 84 |
|
@@ -151,7 +149,11 @@ static String userAgent() { |
151 | 149 | "USER-AGENT", u -> userAgent(), "HOST", u -> u.getRawAuthority()); |
152 | 150 |
|
153 | 151 | @Test(dataProvider = "variants") |
154 | | - void test(String uriString, String headerNameAndValue, boolean sameClient) throws Exception { |
| 152 | + void test(String uriString, |
| 153 | + String headerNameAndValue, |
| 154 | + boolean sameClient) |
| 155 | + throws Exception |
| 156 | + { |
155 | 157 | out.println("\n--- Starting "); |
156 | 158 |
|
157 | 159 | int index = headerNameAndValue.indexOf(":"); |
@@ -183,21 +185,41 @@ void test(String uriString, String headerNameAndValue, boolean sameClient) throw |
183 | 185 | assertEquals(resp.statusCode(), 200, |
184 | 186 | "Expected 200, got:" + resp.statusCode()); |
185 | 187 |
|
186 | | - String receivedHeaderString = value == null ? null |
187 | | - : resp.headers().firstValue("X-"+key).get(); |
188 | | - out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key)); |
189 | | - if (value != null) { |
190 | | - assertEquals(receivedHeaderString, value); |
191 | | - assertEquals(resp.headers().allValues("X-"+key), List.of(value)); |
| 188 | + boolean isInitialRequest = i == 0; |
| 189 | + boolean isSecure = uri.getScheme().equalsIgnoreCase("https"); |
| 190 | + boolean isHTTP2 = resp.version() == HTTP_2; |
| 191 | + boolean isNotH2CUpgrade = isSecure || (sameClient == true && !isInitialRequest); |
| 192 | + boolean isDefaultHostHeader = name.equalsIgnoreCase("host") && useDefault; |
| 193 | + |
| 194 | + // By default, HTTP/2 sets the `:authority:` pseudo-header, instead |
| 195 | + // of the `Host` header. Therefore, there should be no "X-Host" |
| 196 | + // header in the response, except the response to the h2c Upgrade |
| 197 | + // request which will have been sent through HTTP/1.1. |
| 198 | + |
| 199 | + if (isDefaultHostHeader && isHTTP2 && isNotH2CUpgrade) { |
| 200 | + assertTrue(resp.headers().firstValue("X-" + key).isEmpty()); |
| 201 | + assertTrue(resp.headers().allValues("X-" + key).isEmpty()); |
| 202 | + out.println("No X-" + key + " header received, as expected"); |
192 | 203 | } else { |
193 | | - assertEquals(resp.headers().allValues("X-"+key).size(), 0); |
| 204 | + String receivedHeaderString = value == null ? null |
| 205 | + : resp.headers().firstValue("X-"+key).get(); |
| 206 | + out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key)); |
| 207 | + if (value != null) { |
| 208 | + assertEquals(receivedHeaderString, value); |
| 209 | + assertEquals(resp.headers().allValues("X-"+key), List.of(value)); |
| 210 | + } else { |
| 211 | + assertEquals(resp.headers().allValues("X-"+key).size(), 0); |
| 212 | + } |
194 | 213 | } |
195 | | - |
196 | 214 | } |
197 | 215 | } |
198 | 216 |
|
199 | 217 | @Test(dataProvider = "variants") |
200 | | - void testHomeMadeIllegalHeader(String uriString, String headerNameAndValue, boolean sameClient) throws Exception { |
| 218 | + void testHomeMadeIllegalHeader(String uriString, |
| 219 | + String headerNameAndValue, |
| 220 | + boolean sameClient) |
| 221 | + throws Exception |
| 222 | + { |
201 | 223 | out.println("\n--- Starting "); |
202 | 224 | final URI uri = URI.create(uriString); |
203 | 225 |
|
@@ -266,22 +288,39 @@ void testAsync(String uriString, String headerNameAndValue, boolean sameClient) |
266 | 288 | } |
267 | 289 | HttpRequest request = requestBuilder.build(); |
268 | 290 |
|
| 291 | + boolean isInitialRequest = i == 0; |
| 292 | + boolean isSecure = uri.getScheme().equalsIgnoreCase("https"); |
| 293 | + boolean isNotH2CUpgrade = isSecure || (sameClient == true && !isInitialRequest); |
| 294 | + boolean isDefaultHostHeader = name.equalsIgnoreCase("host") && useDefault; |
| 295 | + |
269 | 296 | client.sendAsync(request, BodyHandlers.ofString()) |
270 | 297 | .thenApply(response -> { |
271 | 298 | out.println("Got response: " + response); |
272 | 299 | out.println("Got body: " + response.body()); |
273 | 300 | assertEquals(response.statusCode(), 200); |
274 | 301 | return response;}) |
275 | 302 | .thenAccept(resp -> { |
276 | | - String receivedHeaderString = value == null ? null |
277 | | - : resp.headers().firstValue("X-"+key).get(); |
278 | | - out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key)); |
279 | | - if (value != null) { |
280 | | - assertEquals(receivedHeaderString, value); |
281 | | - assertEquals(resp.headers().allValues("X-" + key), List.of(value)); |
| 303 | + // By default, HTTP/2 sets the `:authority:` pseudo-header, instead |
| 304 | + // of the `Host` header. Therefore, there should be no "X-Host" |
| 305 | + // header in the response, except the response to the h2c Upgrade |
| 306 | + // request which will have been sent through HTTP/1.1. |
| 307 | + |
| 308 | + if (isDefaultHostHeader && resp.version() == HTTP_2 && isNotH2CUpgrade) { |
| 309 | + assertTrue(resp.headers().firstValue("X-" + key).isEmpty()); |
| 310 | + assertTrue(resp.headers().allValues("X-" + key).isEmpty()); |
| 311 | + out.println("No X-" + key + " header received, as expected"); |
282 | 312 | } else { |
283 | | - assertEquals(resp.headers().allValues("X-" + key).size(), 1); |
284 | | - } }) |
| 313 | + String receivedHeaderString = value == null ? null |
| 314 | + : resp.headers().firstValue("X-"+key).get(); |
| 315 | + out.println("Got X-" + key + ": " + resp.headers().allValues("X-"+key)); |
| 316 | + if (value != null) { |
| 317 | + assertEquals(receivedHeaderString, value); |
| 318 | + assertEquals(resp.headers().allValues("X-" + key), List.of(value)); |
| 319 | + } else { |
| 320 | + assertEquals(resp.headers().allValues("X-" + key).size(), 1); |
| 321 | + } |
| 322 | + } |
| 323 | + }) |
285 | 324 | .join(); |
286 | 325 | } |
287 | 326 | } |
|
0 commit comments