View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit;
16  
17  import java.net.URL;
18  import java.net.URLEncoder;
19  import java.nio.charset.Charset;
20  import java.time.Duration;
21  import java.util.Arrays;
22  
23  import org.apache.commons.lang3.StringUtils;
24  import org.htmlunit.junit.annotation.Alerts;
25  import org.htmlunit.junit.annotation.HtmlUnitNYI;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.Test;
28  import org.junit.jupiter.api.condition.DisabledOnOs;
29  import org.junit.jupiter.api.condition.OS;
30  import org.openqa.selenium.By;
31  import org.openqa.selenium.WebDriver;
32  import org.openqa.selenium.support.ui.ExpectedCondition;
33  import org.openqa.selenium.support.ui.Wait;
34  import org.openqa.selenium.support.ui.WebDriverWait;
35  
36  /**
37   * Tests using the {@link PrimitiveWebServer}.
38   *
39   * @author Ahmed Ashour
40   * @author Ronald Brill
41   */
42  public class HttpWebConnection3Test extends WebDriverTestCase {
43  
44      /**
45       * @throws Exception if the test fails
46       */
47      @Test
48      @Alerts(DEFAULT = {HttpHeader.HOST, HttpHeader.CONNECTION, HttpHeader.SEC_CH_UA, HttpHeader.SEC_CH_UA_MOBILE,
49                         HttpHeader.SEC_CH_UA_PLATFORM,
50                         HttpHeader.UPGRADE_INSECURE_REQUESTS, HttpHeader.USER_AGENT, HttpHeader.ACCEPT,
51                         HttpHeader.SEC_FETCH_SITE, HttpHeader.SEC_FETCH_MODE, HttpHeader.SEC_FETCH_USER,
52                         HttpHeader.SEC_FETCH_DEST, HttpHeader.ACCEPT_ENCODING, HttpHeader.ACCEPT_LANGUAGE},
53              FF = {HttpHeader.HOST, HttpHeader.USER_AGENT, HttpHeader.ACCEPT, HttpHeader.ACCEPT_LANGUAGE,
54                    HttpHeader.ACCEPT_ENCODING, HttpHeader.CONNECTION, HttpHeader.UPGRADE_INSECURE_REQUESTS,
55                    HttpHeader.SEC_FETCH_DEST, HttpHeader.SEC_FETCH_MODE, HttpHeader.SEC_FETCH_SITE,
56                    HttpHeader.SEC_FETCH_USER, HttpHeader.PRIORITY},
57              FF_ESR = {HttpHeader.HOST, HttpHeader.USER_AGENT, HttpHeader.ACCEPT, HttpHeader.ACCEPT_LANGUAGE,
58                        HttpHeader.ACCEPT_ENCODING, HttpHeader.CONNECTION, HttpHeader.UPGRADE_INSECURE_REQUESTS,
59                        HttpHeader.SEC_FETCH_DEST, HttpHeader.SEC_FETCH_MODE, HttpHeader.SEC_FETCH_SITE,
60                        HttpHeader.SEC_FETCH_USER, HttpHeader.PRIORITY})
61      public void headers() throws Exception {
62          final String response = "HTTP/1.1 200 OK\r\n"
63              + "Content-Length: 2\r\n"
64              + "Content-Type: text/plain\r\n"
65              + "\r\n"
66              + "Hi";
67  
68          shutDownAll();
69          try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, null)) {
70              final WebDriver driver = getWebDriver();
71  
72              driver.get("http://localhost:" + primitiveWebServer.getPort());
73              final String request = primitiveWebServer.getRequests().get(0);
74              final String[] headers = request.split("\\r\\n");
75              final String[] result = new String[headers.length - 1];
76              for (int i = 0; i < result.length; i++) {
77                  final String header = headers[i + 1];
78                  result[i] = header.substring(0, header.indexOf(':'));
79              }
80              assertEquals(Arrays.asList(getExpectedAlerts()).toString(), Arrays.asList(result).toString());
81          }
82      }
83  
84      /**
85       * @throws Exception if the test fails
86       */
87      @Test
88      @Alerts(DEFAULT = {HttpHeader.HOST, HttpHeader.CONNECTION,
89                         HttpHeader.SEC_CH_UA, HttpHeader.SEC_CH_UA_MOBILE,
90                         HttpHeader.SEC_CH_UA_PLATFORM,
91                         HttpHeader.UPGRADE_INSECURE_REQUESTS,
92                         HttpHeader.USER_AGENT, HttpHeader.ACCEPT, HttpHeader.SEC_FETCH_SITE,
93                         HttpHeader.SEC_FETCH_MODE, HttpHeader.SEC_FETCH_USER, HttpHeader.SEC_FETCH_DEST,
94                         HttpHeader.REFERER, HttpHeader.ACCEPT_ENCODING, HttpHeader.ACCEPT_LANGUAGE,
95                         HttpHeader.COOKIE},
96              FF = {HttpHeader.HOST, HttpHeader.USER_AGENT, HttpHeader.ACCEPT, HttpHeader.ACCEPT_LANGUAGE,
97                    HttpHeader.ACCEPT_ENCODING, HttpHeader.CONNECTION, HttpHeader.REFERER, HttpHeader.COOKIE,
98                    HttpHeader.UPGRADE_INSECURE_REQUESTS, HttpHeader.SEC_FETCH_DEST, HttpHeader.SEC_FETCH_MODE,
99                    HttpHeader.SEC_FETCH_SITE, HttpHeader.SEC_FETCH_USER, HttpHeader.PRIORITY},
100             FF_ESR = {HttpHeader.HOST, HttpHeader.USER_AGENT, HttpHeader.ACCEPT, HttpHeader.ACCEPT_LANGUAGE,
101                       HttpHeader.ACCEPT_ENCODING, HttpHeader.CONNECTION, HttpHeader.REFERER, HttpHeader.COOKIE,
102                       HttpHeader.UPGRADE_INSECURE_REQUESTS, HttpHeader.SEC_FETCH_DEST, HttpHeader.SEC_FETCH_MODE,
103                       HttpHeader.SEC_FETCH_SITE, HttpHeader.SEC_FETCH_USER, HttpHeader.PRIORITY})
104     public void headers_cookie_referer() throws Exception {
105         final String htmlResponse = "<a href='2.html'>Click me</a>";
106         final String response = "HTTP/1.1 200 OK\r\n"
107             + "Content-Length: " + htmlResponse.length() + "\r\n"
108             + "Content-Type: text/html\r\n"
109             + "Set-Cookie: name=value\r\n"
110             + "\r\n"
111             + htmlResponse;
112 
113         shutDownAll();
114         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, null)) {
115             final WebDriver driver = getWebDriver();
116 
117             driver.get("http://localhost:" + primitiveWebServer.getPort());
118             driver.findElement(By.linkText("Click me")).click();
119 
120             final Wait<WebDriver> wait = new WebDriverWait(driver, Duration.ofSeconds(5));
121             wait.until(currentUrlContains("2.html"));
122 
123             int index = 1;
124             String request;
125             do {
126                 request = primitiveWebServer.getRequests().get(index++);
127             }
128             while (request.contains("/favicon.ico"));
129 
130             final String[] headers = request.split("\\r\\n");
131             final String[] result = new String[headers.length - 1];
132             for (int i = 0; i < result.length; i++) {
133                 final String header = headers[i + 1];
134                 result[i] = header.substring(0, header.indexOf(':'));
135             }
136             assertEquals(Arrays.asList(getExpectedAlerts()).toString(), Arrays.asList(result).toString());
137         }
138     }
139 
140     /**
141      * @throws Exception if the test fails
142      */
143     @Test
144     @Alerts("gzip, deflate, br, zstd")
145     @HtmlUnitNYI(CHROME = "gzip, deflate, br",
146             EDGE = "gzip, deflate, br",
147             FF = "gzip, deflate, br",
148             FF_ESR = "gzip, deflate, br")
149     public void acceptEncoding() throws Exception {
150         final String response = "HTTP/1.1 200 OK\r\n"
151             + "Content-Length: 2\r\n"
152             + "Content-Type: text/plain\r\n"
153             + "\r\n"
154             + "Hi";
155 
156         shutDownAll();
157         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, null)) {
158             final WebDriver driver = getWebDriver();
159 
160             driver.get("http://localhost:" + primitiveWebServer.getPort());
161             final String request = primitiveWebServer.getRequests().get(0);
162             final String[] headers = request.split("\\r\\n");
163             for (int i = 0; i < headers.length; i++) {
164                 final String header = headers[i];
165                 if (StringUtils.startsWithIgnoreCase(header, HttpHeader.ACCEPT_ENCODING_LC)) {
166                     final String value = header.substring(header.indexOf(':') + 1);
167                     assertEquals(getExpectedAlerts()[0], value.trim());
168                     return;
169                 }
170             }
171             Assertions.fail("No accept-encoding header found.");
172         }
173     }
174 
175     /**
176      * An expectation for checking that the current url contains a case-sensitive substring.
177      *
178      * @param url the fragment of url expected
179      * @return true when the url matches, false otherwise
180      */
181     public static ExpectedCondition<Boolean> currentUrlContains(final String url) {
182         return new ExpectedCondition<Boolean>() {
183             @Override
184             public Boolean apply(final WebDriver driver) {
185                 final String currentUrl = driver.getCurrentUrl();
186                 return currentUrl != null && currentUrl.contains(url);
187             }
188         };
189     }
190 
191     /**
192      * Test for bug #1898.
193      *
194      * @throws Exception if an error occurs
195      */
196     @Test
197     @Alerts("§§URL§§?????")
198     // seems to work only when running alone
199     public void locationUTF() throws Exception {
200         final String url = "http://localhost:" + PORT_PRIMITIVE_SERVER + "/";
201 
202         final String response = "HTTP/1.1 302 Found\r\n"
203                 + "Content-Length: 0\r\n"
204                 + "Location: " +  url + "\u0623\u0647\u0644\u0627\u064b" + "\r\n"
205                 + "\r\n";
206 
207         final String response2 = "HTTP/1.1 200 OK\r\n"
208                 + "Content-Length: 2\r\n"
209                 + "Content-Type: text/html\r\n"
210                 + "\r\n"
211                 + "Hi";
212 
213         expandExpectedAlertsVariables(new URL(url));
214 
215         shutDownAll();
216         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, response2)) {
217             final WebDriver driver = getWebDriver();
218 
219             driver.get(url);
220             assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
221             assertTrue(driver.getPageSource().contains("Hi"));
222 
223             assertEquals(2, primitiveWebServer.getRequests().size());
224         }
225     }
226 
227     /**
228      * Test for bug #1898.
229      *
230      * @throws Exception if an error occurs
231      */
232     @Test
233     @Alerts("§§URL§§test?%D8%A3%D9%87%D9%84%D8%A7%D9%8B")
234     public void locationQueryUTF8Encoded() throws Exception {
235         final String url = "http://localhost:" + PORT_PRIMITIVE_SERVER + "/";
236 
237         final String response = "HTTP/1.1 302 Found\r\n"
238                 + "Content-Length: 0\r\n"
239                 + "Location: "
240                     +  url
241                     + "test?"
242                     + URLEncoder.encode("\u0623\u0647\u0644\u0627\u064b", "UTF-8")
243                     + "\r\n"
244                 + "\r\n";
245 
246         final String response2 = "HTTP/1.1 200 OK\r\n"
247                 + "Content-Length: 2\r\n"
248                 + "Content-Type: text/html\r\n"
249                 + "\r\n"
250                 + "Hi";
251 
252         expandExpectedAlertsVariables(new URL(url));
253 
254         shutDownAll();
255         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, response2)) {
256             final WebDriver driver = getWebDriver();
257 
258             driver.get(url);
259             Thread.sleep(DEFAULT_WAIT_TIME.toMillis());
260             assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
261             assertEquals(2, primitiveWebServer.getRequests().size());
262             assertTrue(driver.getPageSource(), driver.getPageSource().contains("Hi"));
263         }
264     }
265 
266     /**
267      * Test for bug #1898.
268      *
269      * @throws Exception if an error occurs
270      */
271     @Test
272     @Alerts("§§URL§§%D8%A3%D9%87%D9%84%D8%A7%D9%8B")
273     public void locationUTF8Encoded() throws Exception {
274         final String url = "http://localhost:" + PORT_PRIMITIVE_SERVER + "/";
275 
276         final String response = "HTTP/1.1 302 Found\r\n"
277                 + "Content-Length: 0\r\n"
278                 + "Location: "
279                     +  url
280                     + URLEncoder.encode("\u0623\u0647\u0644\u0627\u064b", "UTF-8")
281                     + "\r\n"
282                 + "\r\n";
283 
284         final String response2 = "HTTP/1.1 200 OK\r\n"
285                 + "Content-Length: 2\r\n"
286                 + "Content-Type: text/html\r\n"
287                 + "\r\n"
288                 + "Hi";
289 
290         expandExpectedAlertsVariables(new URL(url));
291 
292         shutDownAll();
293         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, response2)) {
294             final WebDriver driver = getWebDriver();
295 
296             driver.get(url);
297             assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
298             assertTrue(driver.getPageSource().contains("Hi"));
299 
300             assertEquals(2, primitiveWebServer.getRequests().size());
301         }
302     }
303 
304     /**
305      * Test case for Bug #1882.
306      *
307      * @throws Exception if the test fails
308      */
309     @Test
310     @Alerts("para=%u65E5")
311     @HtmlUnitNYI(CHROME = "para=%25u65E5",
312             EDGE = "para=%25u65E5",
313             FF = "para=%25u65E5",
314             FF_ESR = "para=%25u65E5")
315     public void queryString() throws Exception {
316         final String response = "HTTP/1.1 302 Found\r\n"
317                 + "Content-Length: 0\r\n"
318                 + "\r\n";
319 
320         shutDownAll();
321         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, response, null)) {
322             final WebDriver driver = getWebDriver();
323 
324             driver.get("http://localhost:" + primitiveWebServer.getPort() + "?para=%u65E5");
325             assertTrue(primitiveWebServer.getRequests().get(0),
326                         primitiveWebServer.getRequests().get(0).contains(getExpectedAlerts()[0]));
327         }
328     }
329 
330     /**
331      * Tests a form get request.
332      * @throws Exception if the test fails
333      */
334     @Test
335     @Alerts(CHROME = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
336                       "Host: localhost:§§PORT§§",
337                       "Connection: keep-alive",
338                       "sec-ch-ua: §§SEC_USER_AGENT§§",
339                       "sec-ch-ua-mobile: ?0",
340                       "sec-ch-ua-platform: \"Windows\"",
341                       "Upgrade-Insecure-Requests: 1",
342                       "User-Agent: §§USER_AGENT§§",
343                       "Accept: §§ACCEPT§§",
344                       "Sec-Fetch-Site: same-origin",
345                       "Sec-Fetch-Mode: navigate",
346                       "Sec-Fetch-User: ?1",
347                       "Sec-Fetch-Dest: document",
348                       "Referer: http://localhost:§§PORT§§/",
349                       "Accept-Encoding: gzip, deflate, br, zstd",
350                       "Accept-Language: en-US,en;q=0.9"},
351             EDGE = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
352                     "Host: localhost:§§PORT§§",
353                     "Connection: keep-alive",
354                     "sec-ch-ua: §§SEC_USER_AGENT§§",
355                     "sec-ch-ua-mobile: ?0",
356                     "sec-ch-ua-platform: \"Windows\"",
357                     "Upgrade-Insecure-Requests: 1",
358                     "User-Agent: §§USER_AGENT§§",
359                     "Accept: §§ACCEPT§§",
360                     "Sec-Fetch-Site: same-origin",
361                     "Sec-Fetch-Mode: navigate",
362                     "Sec-Fetch-User: ?1",
363                     "Sec-Fetch-Dest: document",
364                     "Referer: http://localhost:§§PORT§§/",
365                     "Accept-Encoding: gzip, deflate, br, zstd",
366                     "Accept-Language: en-US,en;q=0.9"},
367             FF = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
368                   "Host: localhost:§§PORT§§",
369                   "User-Agent: §§USER_AGENT§§",
370                   "Accept: §§ACCEPT§§",
371                   "Accept-Language: en-US,en;q=0.5",
372                   "Accept-Encoding: gzip, deflate, br, zstd",
373                   "Connection: keep-alive",
374                   "Referer: http://localhost:§§PORT§§/",
375                   "Upgrade-Insecure-Requests: 1",
376                   "Sec-Fetch-Dest: document",
377                   "Sec-Fetch-Mode: navigate",
378                   "Sec-Fetch-Site: same-origin",
379                   "Sec-Fetch-User: ?1",
380                   "Priority: u=0, i"},
381             FF_ESR = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
382                       "Host: localhost:§§PORT§§",
383                       "User-Agent: §§USER_AGENT§§",
384                       "Accept: §§ACCEPT§§",
385                       "Accept-Language: en-US,en;q=0.5",
386                       "Accept-Encoding: gzip, deflate, br, zstd",
387                       "Connection: keep-alive",
388                       "Referer: http://localhost:§§PORT§§/",
389                       "Upgrade-Insecure-Requests: 1",
390                       "Sec-Fetch-Dest: document",
391                       "Sec-Fetch-Mode: navigate",
392                       "Sec-Fetch-Site: same-origin",
393                       "Sec-Fetch-User: ?1",
394                       "Priority: u=0, i"})
395     @HtmlUnitNYI(CHROME = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
396                            "Host: localhost:§§PORT§§",
397                            "Connection: keep-alive",
398                            "sec-ch-ua: §§SEC_USER_AGENT§§",
399                            "sec-ch-ua-mobile: ?0",
400                            "sec-ch-ua-platform: \"Windows\"",
401                            "Upgrade-Insecure-Requests: 1",
402                            "User-Agent: §§USER_AGENT§§",
403                            "Accept: §§ACCEPT§§",
404                            "Sec-Fetch-Site: same-origin",
405                            "Sec-Fetch-Mode: navigate",
406                            "Sec-Fetch-User: ?1",
407                            "Sec-Fetch-Dest: document",
408                            "Referer: http://localhost:§§PORT§§/",
409                            "Accept-Encoding: gzip, deflate, br",
410                            "Accept-Language: en-US,en;q=0.9"},
411             EDGE = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
412                     "Host: localhost:§§PORT§§",
413                     "Connection: keep-alive",
414                     "sec-ch-ua: §§SEC_USER_AGENT§§",
415                     "sec-ch-ua-mobile: ?0",
416                     "sec-ch-ua-platform: \"Windows\"",
417                     "Upgrade-Insecure-Requests: 1",
418                     "User-Agent: §§USER_AGENT§§",
419                     "Accept: §§ACCEPT§§",
420                     "Sec-Fetch-Site: same-origin",
421                     "Sec-Fetch-Mode: navigate",
422                     "Sec-Fetch-User: ?1",
423                     "Sec-Fetch-Dest: document",
424                     "Referer: http://localhost:§§PORT§§/",
425                     "Accept-Encoding: gzip, deflate, br",
426                     "Accept-Language: en-US,en;q=0.9"},
427             FF = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
428                   "Host: localhost:§§PORT§§",
429                   "User-Agent: §§USER_AGENT§§",
430                   "Accept: §§ACCEPT§§",
431                   "Accept-Language: en-US,en;q=0.5",
432                   "Accept-Encoding: gzip, deflate, br",
433                   "Connection: keep-alive",
434                   "Referer: http://localhost:§§PORT§§/",
435                   "Upgrade-Insecure-Requests: 1",
436                   "Sec-Fetch-Dest: document",
437                   "Sec-Fetch-Mode: navigate",
438                   "Sec-Fetch-Site: same-origin",
439                   "Sec-Fetch-User: ?1",
440                   "Priority: u=0, i"},
441             FF_ESR = {"GET /foo?text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21 HTTP/1.1",
442                       "Host: localhost:§§PORT§§",
443                       "User-Agent: §§USER_AGENT§§",
444                       "Accept: §§ACCEPT§§",
445                       "Accept-Language: en-US,en;q=0.5",
446                       "Accept-Encoding: gzip, deflate, br",
447                       "Connection: keep-alive",
448                       "Referer: http://localhost:§§PORT§§/",
449                       "Upgrade-Insecure-Requests: 1",
450                       "Sec-Fetch-Dest: document",
451                       "Sec-Fetch-Mode: navigate",
452                       "Sec-Fetch-Site: same-origin",
453                       "Sec-Fetch-User: ?1",
454                       "Priority: u=0, i"})
455     public void formGet() throws Exception {
456         String html = DOCTYPE_HTML
457             + "<html><body><form action='foo' method='get' accept-charset='iso-8859-1'>\n"
458             + "<input name='text1' value='me &amp;amp; you'>\n"
459             + "<textarea name='text2'>Hello\nworld!</textarea>\n"
460             + "<input type='submit' id='submit'>\n"
461             + "</form></body></html>";
462         html = "HTTP/1.1 200 OK\r\n"
463                 + "Content-Length: " + (html.length()) + "\r\n"
464                 + "Content-Type: text/html\r\n"
465                 + "\r\n"
466                 + html;
467         final String hi = "HTTP/1.1 200 OK\r\n"
468                 + "Content-Length: 2\r\n"
469                 + "Content-Type: text/plain\r\n"
470                 + "\r\n"
471                 + "Hi";
472 
473         shutDownAll();
474         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
475             final WebDriver driver = getWebDriver();
476 
477             driver.get("http://localhost:" + primitiveWebServer.getPort());
478             driver.findElement(By.id("submit")).click();
479 
480             final String[] expectedHeaders = getExpectedAlerts();
481             for (int i = 0; i < expectedHeaders.length; i++) {
482                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
483                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
484                         getBrowserVersion().getUserAgent());
485                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
486                         getBrowserVersion().getSecClientHintUserAgentHeader());
487                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
488                         getBrowserVersion().getHtmlAcceptHeader());
489             }
490             final String request = primitiveWebServer.getRequests().get(1);
491             final String[] headers = request.split("\\r\\n");
492             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
493         }
494     }
495 
496     /**
497      * Tests a form post request.
498      * @throws Exception if the test fails
499      */
500     @Test
501     @Alerts(CHROME = {"POST /foo HTTP/1.1",
502                       "Host: localhost:§§PORT§§",
503                       "Connection: keep-alive",
504                       "Content-Length: 48",
505                       "Cache-Control: max-age=0",
506                       "sec-ch-ua: §§SEC_USER_AGENT§§",
507                       "sec-ch-ua-mobile: ?0",
508                       "sec-ch-ua-platform: \"Windows\"",
509                       "Origin: http://localhost:§§PORT§§",
510                       "Content-Type: application/x-www-form-urlencoded",
511                       "Upgrade-Insecure-Requests: 1",
512                       "User-Agent: §§USER_AGENT§§",
513                       "Accept: §§ACCEPT§§",
514                       "Sec-Fetch-Site: same-origin",
515                       "Sec-Fetch-Mode: navigate",
516                       "Sec-Fetch-User: ?1",
517                       "Sec-Fetch-Dest: document",
518                       "Referer: http://localhost:§§PORT§§/",
519                       "Accept-Encoding: gzip, deflate, br, zstd",
520                       "Accept-Language: en-US,en;q=0.9",
521                       "",
522                       "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
523             EDGE = {"POST /foo HTTP/1.1",
524                     "Host: localhost:§§PORT§§",
525                     "Connection: keep-alive",
526                     "Content-Length: 48",
527                     "Cache-Control: max-age=0",
528                     "sec-ch-ua: §§SEC_USER_AGENT§§",
529                     "sec-ch-ua-mobile: ?0",
530                     "sec-ch-ua-platform: \"Windows\"",
531                     "Origin: http://localhost:§§PORT§§",
532                     "Content-Type: application/x-www-form-urlencoded",
533                     "Upgrade-Insecure-Requests: 1",
534                     "User-Agent: §§USER_AGENT§§",
535                     "Accept: §§ACCEPT§§",
536                     "Sec-Fetch-Site: same-origin",
537                     "Sec-Fetch-Mode: navigate",
538                     "Sec-Fetch-User: ?1",
539                     "Sec-Fetch-Dest: document",
540                     "Referer: http://localhost:§§PORT§§/",
541                     "Accept-Encoding: gzip, deflate, br, zstd",
542                     "Accept-Language: en-US,en;q=0.9",
543                     "",
544                     "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
545             FF = {"POST /foo HTTP/1.1",
546                   "Host: localhost:§§PORT§§",
547                   "User-Agent: §§USER_AGENT§§",
548                   "Accept: §§ACCEPT§§",
549                   "Accept-Language: en-US,en;q=0.5",
550                   "Accept-Encoding: gzip, deflate, br, zstd",
551                   "Content-Type: application/x-www-form-urlencoded",
552                   "Content-Length: 48",
553                   "Origin: http://localhost:§§PORT§§",
554                   "Connection: keep-alive",
555                   "Referer: http://localhost:§§PORT§§/",
556                   "Upgrade-Insecure-Requests: 1",
557                   "Sec-Fetch-Dest: document",
558                   "Sec-Fetch-Mode: navigate",
559                   "Sec-Fetch-Site: same-origin",
560                   "Sec-Fetch-User: ?1",
561                   "Priority: u=0, i",
562                   "",
563                   "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
564             FF_ESR = {"POST /foo HTTP/1.1",
565                       "Host: localhost:§§PORT§§",
566                       "User-Agent: §§USER_AGENT§§",
567                       "Accept: §§ACCEPT§§",
568                       "Accept-Language: en-US,en;q=0.5",
569                       "Accept-Encoding: gzip, deflate, br, zstd",
570                       "Content-Type: application/x-www-form-urlencoded",
571                       "Content-Length: 48",
572                       "Origin: http://localhost:§§PORT§§",
573                       "Connection: keep-alive",
574                       "Referer: http://localhost:§§PORT§§/",
575                       "Upgrade-Insecure-Requests: 1",
576                       "Sec-Fetch-Dest: document",
577                       "Sec-Fetch-Mode: navigate",
578                       "Sec-Fetch-Site: same-origin",
579                       "Sec-Fetch-User: ?1",
580                       "Priority: u=0, i",
581                       "",
582                       "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"})
583     @HtmlUnitNYI(CHROME = {"POST /foo HTTP/1.1",
584                            "Host: localhost:§§PORT§§",
585                            "Connection: keep-alive",
586                            "sec-ch-ua: §§SEC_USER_AGENT§§",
587                            "sec-ch-ua-mobile: ?0",
588                            "sec-ch-ua-platform: \"Windows\"",
589                            "Upgrade-Insecure-Requests: 1",
590                            "User-Agent: §§USER_AGENT§§",
591                            "Accept: §§ACCEPT§§",
592                            "Sec-Fetch-Site: same-origin",
593                            "Sec-Fetch-Mode: navigate",
594                            "Sec-Fetch-User: ?1",
595                            "Sec-Fetch-Dest: document",
596                            "Referer: http://localhost:§§PORT§§/",
597                            "Accept-Encoding: gzip, deflate, br",
598                            "Accept-Language: en-US,en;q=0.9",
599                            "Origin: http://localhost:§§PORT§§",
600                            "Cache-Control: max-age=0",
601                            "Content-Length: 48",
602                            "Content-Type: application/x-www-form-urlencoded",
603                            "",
604                            "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
605             EDGE = {"POST /foo HTTP/1.1",
606                     "Host: localhost:§§PORT§§",
607                     "Connection: keep-alive",
608                     "sec-ch-ua: §§SEC_USER_AGENT§§",
609                     "sec-ch-ua-mobile: ?0",
610                     "sec-ch-ua-platform: \"Windows\"",
611                     "Upgrade-Insecure-Requests: 1",
612                     "User-Agent: §§USER_AGENT§§",
613                     "Accept: §§ACCEPT§§",
614                     "Sec-Fetch-Site: same-origin",
615                     "Sec-Fetch-Mode: navigate",
616                     "Sec-Fetch-User: ?1",
617                     "Sec-Fetch-Dest: document",
618                     "Referer: http://localhost:§§PORT§§/",
619                     "Accept-Encoding: gzip, deflate, br",
620                     "Accept-Language: en-US,en;q=0.9",
621                     "Origin: http://localhost:§§PORT§§",
622                     "Cache-Control: max-age=0",
623                     "Content-Length: 48",
624                     "Content-Type: application/x-www-form-urlencoded",
625                     "",
626                     "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
627             FF = {"POST /foo HTTP/1.1",
628                   "Host: localhost:§§PORT§§",
629                   "User-Agent: §§USER_AGENT§§",
630                   "Accept: §§ACCEPT§§",
631                   "Accept-Language: en-US,en;q=0.5",
632                   "Accept-Encoding: gzip, deflate, br",
633                   "Connection: keep-alive",
634                   "Referer: http://localhost:§§PORT§§/",
635                   "Upgrade-Insecure-Requests: 1",
636                   "Sec-Fetch-Dest: document",
637                   "Sec-Fetch-Mode: navigate",
638                   "Sec-Fetch-Site: same-origin",
639                   "Sec-Fetch-User: ?1",
640                   "Priority: u=0, i",
641                   "Origin: http://localhost:§§PORT§§",
642                   "Content-Length: 48",
643                   "Content-Type: application/x-www-form-urlencoded",
644                   "",
645                   "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"},
646             FF_ESR = {"POST /foo HTTP/1.1",
647                       "Host: localhost:§§PORT§§",
648                       "User-Agent: §§USER_AGENT§§",
649                       "Accept: §§ACCEPT§§",
650                       "Accept-Language: en-US,en;q=0.5",
651                       "Accept-Encoding: gzip, deflate, br",
652                       "Connection: keep-alive",
653                       "Referer: http://localhost:§§PORT§§/",
654                       "Upgrade-Insecure-Requests: 1",
655                       "Sec-Fetch-Dest: document",
656                       "Sec-Fetch-Mode: navigate",
657                       "Sec-Fetch-Site: same-origin",
658                       "Sec-Fetch-User: ?1",
659                       "Priority: u=0, i",
660                       "Origin: http://localhost:§§PORT§§",
661                       "Content-Length: 48",
662                       "Content-Type: application/x-www-form-urlencoded",
663                       "",
664                       "text1=me+%26amp%3B+you&text2=Hello%0D%0Aworld%21"})
665     public void formPost() throws Exception {
666         String html = DOCTYPE_HTML
667             + "<html><body><form action='foo' method='post' accept-charset='iso-8859-1'>\n"
668             + "<input name='text1' value='me &amp;amp; you'>\n"
669             + "<textarea name='text2'>Hello\nworld!</textarea>\n"
670             + "<input type='submit' id='submit'>\n"
671             + "</form></body></html>";
672         html = "HTTP/1.1 200 OK\r\n"
673                 + "Content-Length: " + (html.length()) + "\r\n"
674                 + "Content-Type: text/html\r\n"
675                 + "\r\n"
676                 + html;
677         final String hi = "HTTP/1.1 200 OK\r\n"
678                 + "Content-Length: 2\r\n"
679                 + "Content-Type: text/plain\r\n"
680                 + "\r\n"
681                 + "Hi";
682 
683         shutDownAll();
684         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
685             final WebDriver driver = getWebDriver();
686 
687             driver.get("http://localhost:" + primitiveWebServer.getPort());
688             Thread.sleep(4_000);
689             driver.findElement(By.id("submit")).click();
690 
691             final String[] expectedHeaders = getExpectedAlerts();
692             for (int i = 0; i < expectedHeaders.length; i++) {
693                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
694                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
695                         getBrowserVersion().getUserAgent());
696                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
697                         getBrowserVersion().getSecClientHintUserAgentHeader());
698                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
699                         getBrowserVersion().getHtmlAcceptHeader());
700             }
701             final String request = primitiveWebServer.getRequests().get(1);
702             final String[] headers = request.split("\\r\\n");
703             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
704         }
705     }
706 
707     /**
708      * Tests a anchor click request.
709      * @throws Exception if the test fails
710      */
711     @Test
712     @Alerts(CHROME = {"GET /2.html HTTP/1.1",
713                       "Host: localhost:§§PORT§§",
714                       "Connection: keep-alive",
715                       "sec-ch-ua: §§SEC_USER_AGENT§§",
716                       "sec-ch-ua-mobile: ?0",
717                       "sec-ch-ua-platform: \"Windows\"",
718                       "Upgrade-Insecure-Requests: 1",
719                       "User-Agent: §§USER_AGENT§§",
720                       "Accept: §§ACCEPT§§",
721                       "Sec-Fetch-Site: same-origin",
722                       "Sec-Fetch-Mode: navigate",
723                       "Sec-Fetch-User: ?1",
724                       "Sec-Fetch-Dest: document",
725                       "Referer: http://localhost:§§PORT§§/",
726                       "Accept-Encoding: gzip, deflate, br, zstd",
727                       "Accept-Language: en-US,en;q=0.9"},
728             EDGE = {"GET /2.html HTTP/1.1",
729                     "Host: localhost:§§PORT§§",
730                     "Connection: keep-alive",
731                     "sec-ch-ua: §§SEC_USER_AGENT§§",
732                     "sec-ch-ua-mobile: ?0",
733                     "sec-ch-ua-platform: \"Windows\"",
734                     "Upgrade-Insecure-Requests: 1",
735                     "User-Agent: §§USER_AGENT§§",
736                     "Accept: §§ACCEPT§§",
737                     "Sec-Fetch-Site: same-origin",
738                     "Sec-Fetch-Mode: navigate",
739                     "Sec-Fetch-User: ?1",
740                     "Sec-Fetch-Dest: document",
741                     "Referer: http://localhost:§§PORT§§/",
742                     "Accept-Encoding: gzip, deflate, br, zstd",
743                     "Accept-Language: en-US,en;q=0.9"},
744             FF = {"GET /2.html HTTP/1.1",
745                   "Host: localhost:§§PORT§§",
746                   "User-Agent: §§USER_AGENT§§",
747                   "Accept: §§ACCEPT§§",
748                   "Accept-Language: en-US,en;q=0.5",
749                   "Accept-Encoding: gzip, deflate, br, zstd",
750                   "Connection: keep-alive",
751                   "Referer: http://localhost:§§PORT§§/",
752                   "Upgrade-Insecure-Requests: 1",
753                   "Sec-Fetch-Dest: document",
754                   "Sec-Fetch-Mode: navigate",
755                   "Sec-Fetch-Site: same-origin",
756                   "Sec-Fetch-User: ?1",
757                   "Priority: u=0, i"},
758             FF_ESR = {"GET /2.html HTTP/1.1",
759                       "Host: localhost:§§PORT§§",
760                       "User-Agent: §§USER_AGENT§§",
761                       "Accept: §§ACCEPT§§",
762                       "Accept-Language: en-US,en;q=0.5",
763                       "Accept-Encoding: gzip, deflate, br, zstd",
764                       "Connection: keep-alive",
765                       "Referer: http://localhost:§§PORT§§/",
766                       "Upgrade-Insecure-Requests: 1",
767                       "Sec-Fetch-Dest: document",
768                       "Sec-Fetch-Mode: navigate",
769                       "Sec-Fetch-Site: same-origin",
770                       "Sec-Fetch-User: ?1",
771                       "Priority: u=0, i"})
772     @HtmlUnitNYI(CHROME = {"GET /2.html HTTP/1.1",
773                            "Host: localhost:§§PORT§§",
774                            "Connection: keep-alive",
775                            "sec-ch-ua: §§SEC_USER_AGENT§§",
776                            "sec-ch-ua-mobile: ?0",
777                            "sec-ch-ua-platform: \"Windows\"",
778                            "Upgrade-Insecure-Requests: 1",
779                            "User-Agent: §§USER_AGENT§§",
780                            "Accept: §§ACCEPT§§",
781                            "Sec-Fetch-Site: same-origin",
782                            "Sec-Fetch-Mode: navigate",
783                            "Sec-Fetch-User: ?1",
784                            "Sec-Fetch-Dest: document",
785                            "Referer: http://localhost:§§PORT§§/",
786                            "Accept-Encoding: gzip, deflate, br",
787                            "Accept-Language: en-US,en;q=0.9"},
788             EDGE = {"GET /2.html HTTP/1.1",
789                     "Host: localhost:§§PORT§§",
790                     "Connection: keep-alive",
791                     "sec-ch-ua: §§SEC_USER_AGENT§§",
792                     "sec-ch-ua-mobile: ?0",
793                     "sec-ch-ua-platform: \"Windows\"",
794                     "Upgrade-Insecure-Requests: 1",
795                     "User-Agent: §§USER_AGENT§§",
796                     "Accept: §§ACCEPT§§",
797                     "Sec-Fetch-Site: same-origin",
798                     "Sec-Fetch-Mode: navigate",
799                     "Sec-Fetch-User: ?1",
800                     "Sec-Fetch-Dest: document",
801                     "Referer: http://localhost:§§PORT§§/",
802                     "Accept-Encoding: gzip, deflate, br",
803                     "Accept-Language: en-US,en;q=0.9"},
804             FF = {"GET /2.html HTTP/1.1",
805                   "Host: localhost:§§PORT§§",
806                   "User-Agent: §§USER_AGENT§§",
807                   "Accept: §§ACCEPT§§",
808                   "Accept-Language: en-US,en;q=0.5",
809                   "Accept-Encoding: gzip, deflate, br",
810                   "Connection: keep-alive",
811                   "Referer: http://localhost:§§PORT§§/",
812                   "Upgrade-Insecure-Requests: 1",
813                   "Sec-Fetch-Dest: document",
814                   "Sec-Fetch-Mode: navigate",
815                   "Sec-Fetch-Site: same-origin",
816                   "Sec-Fetch-User: ?1",
817                   "Priority: u=0, i"},
818             FF_ESR = {"GET /2.html HTTP/1.1",
819                       "Host: localhost:§§PORT§§",
820                       "User-Agent: §§USER_AGENT§§",
821                       "Accept: §§ACCEPT§§",
822                       "Accept-Language: en-US,en;q=0.5",
823                       "Accept-Encoding: gzip, deflate, br",
824                       "Connection: keep-alive",
825                       "Referer: http://localhost:§§PORT§§/",
826                       "Upgrade-Insecure-Requests: 1",
827                       "Sec-Fetch-Dest: document",
828                       "Sec-Fetch-Mode: navigate",
829                       "Sec-Fetch-Site: same-origin",
830                       "Sec-Fetch-User: ?1",
831                       "Priority: u=0, i"})
832     public void anchor() throws Exception {
833         String html = DOCTYPE_HTML
834                 + "<html><body><a id='my' href='2.html'>Click me</a></body></html>";
835         html = "HTTP/1.1 200 OK\r\n"
836                 + "Content-Length: " + (html.length()) + "\r\n"
837                 + "Content-Type: text/html\r\n"
838                 + "\r\n"
839                 + html;
840         final String hi = "HTTP/1.1 200 OK\r\n"
841                 + "Content-Length: 2\r\n"
842                 + "Content-Type: text/plain\r\n"
843                 + "\r\n"
844                 + "Hi";
845 
846         shutDownAll();
847         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
848             final WebDriver driver = getWebDriver();
849 
850             driver.get("http://localhost:" + primitiveWebServer.getPort());
851             driver.findElement(By.id("my")).click();
852 
853             final String[] expectedHeaders = getExpectedAlerts();
854             for (int i = 0; i < expectedHeaders.length; i++) {
855                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
856                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
857                         getBrowserVersion().getUserAgent());
858                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
859                         getBrowserVersion().getSecClientHintUserAgentHeader());
860                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
861                         getBrowserVersion().getHtmlAcceptHeader());
862             }
863             final String request = primitiveWebServer.getRequests().get(1);
864             final String[] headers = request.split("\\r\\n");
865             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
866         }
867     }
868 
869     /**
870      * Tests a location href change.
871      * @throws Exception if the test fails
872      */
873     @Test
874     @Alerts(CHROME = {"GET /foo HTTP/1.1",
875                       "Host: localhost:§§PORT§§",
876                       "Connection: keep-alive",
877                       "sec-ch-ua: §§SEC_USER_AGENT§§",
878                       "sec-ch-ua-mobile: ?0",
879                       "sec-ch-ua-platform: \"Windows\"",
880                       "Upgrade-Insecure-Requests: 1",
881                       "User-Agent: §§USER_AGENT§§",
882                       "Accept: §§ACCEPT§§",
883                       "Sec-Fetch-Site: same-origin",
884                       "Sec-Fetch-Mode: navigate",
885                       "Sec-Fetch-Dest: document",
886                       "Referer: http://localhost:§§PORT§§/",
887                       "Accept-Encoding: gzip, deflate, br, zstd",
888                       "Accept-Language: en-US,en;q=0.9"},
889             EDGE = {"GET /foo HTTP/1.1",
890                     "Host: localhost:§§PORT§§",
891                     "Connection: keep-alive",
892                     "sec-ch-ua: §§SEC_USER_AGENT§§",
893                     "sec-ch-ua-mobile: ?0",
894                     "sec-ch-ua-platform: \"Windows\"",
895                     "Upgrade-Insecure-Requests: 1",
896                     "User-Agent: §§USER_AGENT§§",
897                     "Accept: §§ACCEPT§§",
898                     "Sec-Fetch-Site: same-origin",
899                     "Sec-Fetch-Mode: navigate",
900                     "Sec-Fetch-Dest: document",
901                     "Referer: http://localhost:§§PORT§§/",
902                     "Accept-Encoding: gzip, deflate, br, zstd",
903                     "Accept-Language: en-US,en;q=0.9"},
904             FF = {"GET /foo HTTP/1.1",
905                   "Host: localhost:§§PORT§§",
906                   "User-Agent: §§USER_AGENT§§",
907                   "Accept: §§ACCEPT§§",
908                   "Accept-Language: en-US,en;q=0.5",
909                   "Accept-Encoding: gzip, deflate, br, zstd",
910                   "Connection: keep-alive",
911                   "Referer: http://localhost:§§PORT§§/",
912                   "Upgrade-Insecure-Requests: 1",
913                   "Sec-Fetch-Dest: document",
914                   "Sec-Fetch-Mode: navigate",
915                   "Sec-Fetch-Site: same-origin",
916                   "Priority: u=0, i"},
917             FF_ESR = {"GET /foo HTTP/1.1",
918                       "Host: localhost:§§PORT§§",
919                       "User-Agent: §§USER_AGENT§§",
920                       "Accept: §§ACCEPT§§",
921                       "Accept-Language: en-US,en;q=0.5",
922                       "Accept-Encoding: gzip, deflate, br, zstd",
923                       "Connection: keep-alive",
924                       "Referer: http://localhost:§§PORT§§/",
925                       "Upgrade-Insecure-Requests: 1",
926                       "Sec-Fetch-Dest: document",
927                       "Sec-Fetch-Mode: navigate",
928                       "Sec-Fetch-Site: same-origin",
929                       "Priority: u=0, i"})
930     @HtmlUnitNYI(CHROME = {"GET /foo HTTP/1.1",
931                            "Host: localhost:§§PORT§§",
932                            "Connection: keep-alive",
933                            "sec-ch-ua: §§SEC_USER_AGENT§§",
934                            "sec-ch-ua-mobile: ?0",
935                            "sec-ch-ua-platform: \"Windows\"",
936                            "Upgrade-Insecure-Requests: 1",
937                            "User-Agent: §§USER_AGENT§§",
938                            "Accept: §§ACCEPT§§",
939                            "Sec-Fetch-Site: same-origin",
940                            "Sec-Fetch-Mode: navigate",
941                            "Sec-Fetch-User: ?1",
942                            "Sec-Fetch-Dest: document",
943                            "Referer: http://localhost:§§PORT§§/",
944                            "Accept-Encoding: gzip, deflate, br",
945                            "Accept-Language: en-US,en;q=0.9"},
946             EDGE = {"GET /foo HTTP/1.1",
947                     "Host: localhost:§§PORT§§",
948                     "Connection: keep-alive",
949                     "sec-ch-ua: §§SEC_USER_AGENT§§",
950                     "sec-ch-ua-mobile: ?0",
951                     "sec-ch-ua-platform: \"Windows\"",
952                     "Upgrade-Insecure-Requests: 1",
953                     "User-Agent: §§USER_AGENT§§",
954                     "Accept: §§ACCEPT§§",
955                     "Sec-Fetch-Site: same-origin",
956                     "Sec-Fetch-Mode: navigate",
957                     "Sec-Fetch-User: ?1",
958                     "Sec-Fetch-Dest: document",
959                     "Referer: http://localhost:§§PORT§§/",
960                     "Accept-Encoding: gzip, deflate, br",
961                     "Accept-Language: en-US,en;q=0.9"},
962             FF = {"GET /foo HTTP/1.1",
963                   "Host: localhost:§§PORT§§",
964                   "User-Agent: §§USER_AGENT§§",
965                   "Accept: §§ACCEPT§§",
966                   "Accept-Language: en-US,en;q=0.5",
967                   "Accept-Encoding: gzip, deflate, br",
968                   "Connection: keep-alive",
969                   "Referer: http://localhost:§§PORT§§/",
970                   "Upgrade-Insecure-Requests: 1",
971                   "Sec-Fetch-Dest: document",
972                   "Sec-Fetch-Mode: navigate",
973                   "Sec-Fetch-Site: same-origin",
974                   "Sec-Fetch-User: ?1",
975                   "Priority: u=0, i"},
976             FF_ESR = {"GET /foo HTTP/1.1",
977                       "Host: localhost:§§PORT§§",
978                       "User-Agent: §§USER_AGENT§§",
979                       "Accept: §§ACCEPT§§",
980                       "Accept-Language: en-US,en;q=0.5",
981                       "Accept-Encoding: gzip, deflate, br",
982                       "Connection: keep-alive",
983                       "Referer: http://localhost:§§PORT§§/",
984                       "Upgrade-Insecure-Requests: 1",
985                       "Sec-Fetch-Dest: document",
986                       "Sec-Fetch-Mode: navigate",
987                       "Sec-Fetch-Site: same-origin",
988                       "Sec-Fetch-User: ?1",
989                       "Priority: u=0, i"})
990     public void locationSetHref() throws Exception {
991         final String url = "http://localhost:" + WebTestCase.PORT_PRIMITIVE_SERVER;
992         String html = DOCTYPE_HTML
993                 + "<html><body><script>location.href='" + url + "/foo';</script></body></html>";
994         html = "HTTP/1.1 200 OK\r\n"
995                 + "Content-Length: " + (html.length()) + "\r\n"
996                 + "Content-Type: text/html\r\n"
997                 + "\r\n"
998                 + html;
999         final String hi = "HTTP/1.1 200 OK\r\n"
1000                 + "Content-Length: 2\r\n"
1001                 + "Content-Type: text/plain\r\n"
1002                 + "\r\n"
1003                 + "Hi";
1004 
1005         shutDownAll();
1006         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
1007             final WebDriver driver = getWebDriver();
1008 
1009             driver.get("http://localhost:" + primitiveWebServer.getPort());
1010 
1011             final String[] expectedHeaders = getExpectedAlerts();
1012             for (int i = 0; i < expectedHeaders.length; i++) {
1013                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
1014                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
1015                         getBrowserVersion().getUserAgent());
1016                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
1017                         getBrowserVersion().getSecClientHintUserAgentHeader());
1018                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
1019                         getBrowserVersion().getHtmlAcceptHeader());
1020             }
1021             final String request = primitiveWebServer.getRequests().get(1);
1022             final String[] headers = request.split("\\r\\n");
1023             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
1024         }
1025     }
1026 
1027     /**
1028      * Tests a location href change.
1029      * @throws Exception if the test fails
1030      */
1031     @Test
1032     @Alerts(CHROME = {"GET /?newSearch HTTP/1.1",
1033                       "Host: localhost:§§PORT§§",
1034                       "Connection: keep-alive",
1035                       "sec-ch-ua: §§SEC_USER_AGENT§§",
1036                       "sec-ch-ua-mobile: ?0",
1037                       "sec-ch-ua-platform: \"Windows\"",
1038                       "Upgrade-Insecure-Requests: 1",
1039                       "User-Agent: §§USER_AGENT§§",
1040                       "Accept: §§ACCEPT§§",
1041                       "Sec-Fetch-Site: same-origin",
1042                       "Sec-Fetch-Mode: navigate",
1043                       "Sec-Fetch-Dest: document",
1044                       "Referer: http://localhost:§§PORT§§/",
1045                       "Accept-Encoding: gzip, deflate, br, zstd",
1046                       "Accept-Language: en-US,en;q=0.9"},
1047             EDGE = {"GET /?newSearch HTTP/1.1",
1048                     "Host: localhost:§§PORT§§",
1049                     "Connection: keep-alive",
1050                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1051                     "sec-ch-ua-mobile: ?0",
1052                     "sec-ch-ua-platform: \"Windows\"",
1053                     "Upgrade-Insecure-Requests: 1",
1054                     "User-Agent: §§USER_AGENT§§",
1055                     "Accept: §§ACCEPT§§",
1056                     "Sec-Fetch-Site: same-origin",
1057                     "Sec-Fetch-Mode: navigate",
1058                     "Sec-Fetch-Dest: document",
1059                     "Referer: http://localhost:§§PORT§§/",
1060                     "Accept-Encoding: gzip, deflate, br, zstd",
1061                     "Accept-Language: en-US,en;q=0.9"},
1062             FF = {"GET /?newSearch HTTP/1.1",
1063                   "Host: localhost:§§PORT§§",
1064                   "User-Agent: §§USER_AGENT§§",
1065                   "Accept: §§ACCEPT§§",
1066                   "Accept-Language: en-US,en;q=0.5",
1067                   "Accept-Encoding: gzip, deflate, br, zstd",
1068                   "Connection: keep-alive",
1069                   "Referer: http://localhost:§§PORT§§/",
1070                   "Upgrade-Insecure-Requests: 1",
1071                   "Sec-Fetch-Dest: document",
1072                   "Sec-Fetch-Mode: navigate",
1073                   "Sec-Fetch-Site: same-origin",
1074                   "Priority: u=0, i"},
1075             FF_ESR = {"GET /?newSearch HTTP/1.1",
1076                       "Host: localhost:§§PORT§§",
1077                       "User-Agent: §§USER_AGENT§§",
1078                       "Accept: §§ACCEPT§§",
1079                       "Accept-Language: en-US,en;q=0.5",
1080                       "Accept-Encoding: gzip, deflate, br, zstd",
1081                       "Connection: keep-alive",
1082                       "Referer: http://localhost:§§PORT§§/",
1083                       "Upgrade-Insecure-Requests: 1",
1084                       "Sec-Fetch-Dest: document",
1085                       "Sec-Fetch-Mode: navigate",
1086                       "Sec-Fetch-Site: same-origin",
1087                       "Priority: u=0, i"})
1088     @HtmlUnitNYI(CHROME = {"GET /?newSearch HTTP/1.1",
1089                            "Host: localhost:§§PORT§§",
1090                            "Connection: keep-alive",
1091                            "sec-ch-ua: §§SEC_USER_AGENT§§",
1092                            "sec-ch-ua-mobile: ?0",
1093                            "sec-ch-ua-platform: \"Windows\"",
1094                            "Upgrade-Insecure-Requests: 1",
1095                            "User-Agent: §§USER_AGENT§§",
1096                            "Accept: §§ACCEPT§§",
1097                            "Sec-Fetch-Site: same-origin",
1098                            "Sec-Fetch-Mode: navigate",
1099                            "Sec-Fetch-User: ?1",
1100                            "Sec-Fetch-Dest: document",
1101                            "Referer: http://localhost:§§PORT§§/",
1102                            "Accept-Encoding: gzip, deflate, br",
1103                            "Accept-Language: en-US,en;q=0.9"},
1104             EDGE = {"GET /?newSearch HTTP/1.1",
1105                     "Host: localhost:§§PORT§§",
1106                     "Connection: keep-alive",
1107                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1108                     "sec-ch-ua-mobile: ?0",
1109                     "sec-ch-ua-platform: \"Windows\"",
1110                     "Upgrade-Insecure-Requests: 1",
1111                     "User-Agent: §§USER_AGENT§§",
1112                     "Accept: §§ACCEPT§§",
1113                     "Sec-Fetch-Site: same-origin",
1114                     "Sec-Fetch-Mode: navigate",
1115                     "Sec-Fetch-User: ?1",
1116                     "Sec-Fetch-Dest: document",
1117                     "Referer: http://localhost:§§PORT§§/",
1118                     "Accept-Encoding: gzip, deflate, br",
1119                     "Accept-Language: en-US,en;q=0.9"},
1120             FF = {"GET /?newSearch HTTP/1.1",
1121                   "Host: localhost:§§PORT§§",
1122                   "User-Agent: §§USER_AGENT§§",
1123                   "Accept: §§ACCEPT§§",
1124                   "Accept-Language: en-US,en;q=0.5",
1125                   "Accept-Encoding: gzip, deflate, br",
1126                   "Connection: keep-alive",
1127                   "Referer: http://localhost:§§PORT§§/",
1128                   "Upgrade-Insecure-Requests: 1",
1129                   "Sec-Fetch-Dest: document",
1130                   "Sec-Fetch-Mode: navigate",
1131                   "Sec-Fetch-Site: same-origin",
1132                   "Sec-Fetch-User: ?1",
1133                   "Priority: u=0, i"},
1134             FF_ESR = {"GET /?newSearch HTTP/1.1",
1135                       "Host: localhost:§§PORT§§",
1136                       "User-Agent: §§USER_AGENT§§",
1137                       "Accept: §§ACCEPT§§",
1138                       "Accept-Language: en-US,en;q=0.5",
1139                       "Accept-Encoding: gzip, deflate, br",
1140                       "Connection: keep-alive",
1141                       "Referer: http://localhost:§§PORT§§/",
1142                       "Upgrade-Insecure-Requests: 1",
1143                       "Sec-Fetch-Dest: document",
1144                       "Sec-Fetch-Mode: navigate",
1145                       "Sec-Fetch-Site: same-origin",
1146                       "Sec-Fetch-User: ?1",
1147                       "Priority: u=0, i"})
1148     public void locationSetSearch() throws Exception {
1149         String html = DOCTYPE_HTML
1150                 + "<html><body><script>location.search='newSearch';</script></body></html>";
1151         html = "HTTP/1.1 200 OK\r\n"
1152                 + "Content-Length: " + (html.length()) + "\r\n"
1153                 + "Content-Type: text/html\r\n"
1154                 + "\r\n"
1155                 + html;
1156         final String hi = "HTTP/1.1 200 OK\r\n"
1157                 + "Content-Length: 2\r\n"
1158                 + "Content-Type: text/plain\r\n"
1159                 + "\r\n"
1160                 + "Hi";
1161 
1162         shutDownAll();
1163         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
1164             final WebDriver driver = getWebDriver();
1165 
1166             driver.get("http://localhost:" + primitiveWebServer.getPort());
1167 
1168             final String[] expectedHeaders = getExpectedAlerts();
1169             for (int i = 0; i < expectedHeaders.length; i++) {
1170                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
1171                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
1172                         getBrowserVersion().getUserAgent());
1173                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
1174                         getBrowserVersion().getSecClientHintUserAgentHeader());
1175                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
1176                         getBrowserVersion().getHtmlAcceptHeader());
1177             }
1178             final String request = primitiveWebServer.getRequests().get(1);
1179             final String[] headers = request.split("\\r\\n");
1180             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
1181         }
1182     }
1183 
1184     /**
1185      * @throws Exception if the test fails
1186      */
1187     @Test
1188     @Alerts(CHROME = {"GET /script.js HTTP/1.1",
1189                       "Host: localhost:§§PORT§§",
1190                       "Connection: keep-alive",
1191                       "sec-ch-ua-platform: \"Windows\"",
1192                       "User-Agent: §§USER_AGENT§§",
1193                       "sec-ch-ua: §§SEC_USER_AGENT§§",
1194                       "sec-ch-ua-mobile: ?0",
1195                       "Accept: §§ACCEPT§§",
1196                       "Sec-Fetch-Site: same-origin",
1197                       "Sec-Fetch-Mode: no-cors",
1198                       "Sec-Fetch-Dest: script",
1199                       "Referer: http://localhost:§§PORT§§/",
1200                       "Accept-Encoding: gzip, deflate, br, zstd",
1201                       "Accept-Language: en-US,en;q=0.9"},
1202             EDGE = {"GET /script.js HTTP/1.1",
1203                     "Host: localhost:§§PORT§§",
1204                     "Connection: keep-alive",
1205                     "sec-ch-ua-platform: \"Windows\"",
1206                     "User-Agent: §§USER_AGENT§§",
1207                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1208                     "sec-ch-ua-mobile: ?0",
1209                     "Accept: §§ACCEPT§§",
1210                     "Sec-Fetch-Site: same-origin",
1211                     "Sec-Fetch-Mode: no-cors",
1212                     "Sec-Fetch-Dest: script",
1213                     "Referer: http://localhost:§§PORT§§/",
1214                     "Accept-Encoding: gzip, deflate, br, zstd",
1215                     "Accept-Language: en-US,en;q=0.9"},
1216             FF = {"GET /script.js HTTP/1.1",
1217                   "Host: localhost:§§PORT§§",
1218                   "User-Agent: §§USER_AGENT§§",
1219                   "Accept: §§ACCEPT§§",
1220                   "Accept-Language: en-US,en;q=0.5",
1221                   "Accept-Encoding: gzip, deflate, br, zstd",
1222                   "Connection: keep-alive",
1223                   "Referer: http://localhost:§§PORT§§/",
1224                   "Sec-Fetch-Dest: script",
1225                   "Sec-Fetch-Mode: no-cors",
1226                   "Sec-Fetch-Site: same-origin",
1227                   "Priority: u=2"},
1228             FF_ESR = {"GET /script.js HTTP/1.1",
1229                       "Host: localhost:§§PORT§§",
1230                       "User-Agent: §§USER_AGENT§§",
1231                       "Accept: §§ACCEPT§§",
1232                       "Accept-Language: en-US,en;q=0.5",
1233                       "Accept-Encoding: gzip, deflate, br, zstd",
1234                       "Connection: keep-alive",
1235                       "Referer: http://localhost:§§PORT§§/",
1236                       "Sec-Fetch-Dest: script",
1237                       "Sec-Fetch-Mode: no-cors",
1238                       "Sec-Fetch-Site: same-origin",
1239                       "Priority: u=2"})
1240     @HtmlUnitNYI(CHROME = {"GET /script.js HTTP/1.1",
1241                            "Host: localhost:§§PORT§§",
1242                            "Connection: keep-alive",
1243                            "sec-ch-ua: §§SEC_USER_AGENT§§",
1244                            "sec-ch-ua-mobile: ?0",
1245                            "sec-ch-ua-platform: \"Windows\"",
1246                            "Upgrade-Insecure-Requests: 1", // wrong
1247                            "User-Agent: §§USER_AGENT§§",
1248                            "Accept: §§ACCEPT§§",
1249                            "Sec-Fetch-Site: same-origin",
1250                            "Sec-Fetch-Mode: no-cors",
1251                            "Sec-Fetch-User: ?1", // wrong
1252                            "Sec-Fetch-Dest: script",
1253                            "Referer: http://localhost:§§PORT§§/",
1254                            "Accept-Encoding: gzip, deflate, br",
1255                            "Accept-Language: en-US,en;q=0.9"},
1256             EDGE = {"GET /script.js HTTP/1.1",
1257                     "Host: localhost:§§PORT§§",
1258                     "Connection: keep-alive",
1259                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1260                     "sec-ch-ua-mobile: ?0",
1261                     "sec-ch-ua-platform: \"Windows\"",
1262                     "Upgrade-Insecure-Requests: 1", // wrong
1263                     "User-Agent: §§USER_AGENT§§",
1264                     "Accept: §§ACCEPT§§",
1265                     "Sec-Fetch-Site: same-origin",
1266                     "Sec-Fetch-Mode: no-cors",
1267                     "Sec-Fetch-User: ?1", // wrong
1268                     "Sec-Fetch-Dest: script",
1269                     "Referer: http://localhost:§§PORT§§/",
1270                     "Accept-Encoding: gzip, deflate, br",
1271                     "Accept-Language: en-US,en;q=0.9"},
1272             FF = {"GET /script.js HTTP/1.1",
1273                   "Host: localhost:§§PORT§§",
1274                   "User-Agent: §§USER_AGENT§§",
1275                   "Accept: §§ACCEPT§§",
1276                   "Accept-Language: en-US,en;q=0.5",
1277                   "Accept-Encoding: gzip, deflate, br",
1278                   "Connection: keep-alive",
1279                   "Referer: http://localhost:§§PORT§§/",
1280                   "Upgrade-Insecure-Requests: 1", // wrong
1281                   "Sec-Fetch-Dest: script",
1282                   "Sec-Fetch-Mode: no-cors",
1283                   "Sec-Fetch-Site: same-origin",
1284                   "Sec-Fetch-User: ?1", /* wrong */
1285                   "Priority: u=0, i"},
1286             FF_ESR = {"GET /script.js HTTP/1.1",
1287                       "Host: localhost:§§PORT§§",
1288                       "User-Agent: §§USER_AGENT§§",
1289                       "Accept: §§ACCEPT§§",
1290                       "Accept-Language: en-US,en;q=0.5",
1291                       "Accept-Encoding: gzip, deflate, br",
1292                       "Connection: keep-alive",
1293                       "Referer: http://localhost:§§PORT§§/",
1294                       "Upgrade-Insecure-Requests: 1", // wrong
1295                       "Sec-Fetch-Dest: script",
1296                       "Sec-Fetch-Mode: no-cors",
1297                       "Sec-Fetch-Site: same-origin",
1298                       "Sec-Fetch-User: ?1", /* wrong */
1299                       "Priority: u=0, i"})
1300     public void loadJavascript() throws Exception {
1301         String html = DOCTYPE_HTML
1302                 + "<html><head> <script src=\"script.js\"></script> </head><body></body></html>";
1303         html = "HTTP/1.1 200 OK\r\n"
1304                 + "Content-Length: " + (html.length()) + "\r\n"
1305                 + "Content-Type: text/html\r\n"
1306                 + "\r\n"
1307                 + html;
1308         final String hi = "HTTP/1.1 200 OK\r\n"
1309                 + "Content-Length: 2\r\n"
1310                 + "Content-Type: text/javascript\r\n"
1311                 + "\r\n"
1312                 + ";;";
1313 
1314         shutDownAll();
1315         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(null, html, hi)) {
1316             final WebDriver driver = getWebDriver();
1317 
1318             driver.get("http://localhost:" + primitiveWebServer.getPort());
1319 
1320             final String[] expectedHeaders = getExpectedAlerts();
1321             for (int i = 0; i < expectedHeaders.length; i++) {
1322                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
1323                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
1324                         getBrowserVersion().getUserAgent());
1325                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
1326                         getBrowserVersion().getSecClientHintUserAgentHeader());
1327                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
1328                         getBrowserVersion().getScriptAcceptHeader());
1329             }
1330             final String request = primitiveWebServer.getRequests().get(1);
1331             final String[] headers = request.split("\\r\\n");
1332             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
1333         }
1334     }
1335 
1336     /**
1337      * @throws Exception if the test fails
1338      */
1339     @Test
1340     @Alerts(CHROME = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1341                       "Host: localhost:§§PORT§§",
1342                       "Connection: keep-alive",
1343                       "sec-ch-ua-platform: \"Windows\"",
1344                       "User-Agent: §§USER_AGENT§§",
1345                       "sec-ch-ua: §§SEC_USER_AGENT§§",
1346                       "sec-ch-ua-mobile: ?0",
1347                       "Accept: §§ACCEPT§§",
1348                       "Sec-Fetch-Site: same-origin",
1349                       "Sec-Fetch-Mode: no-cors",
1350                       "Sec-Fetch-Dest: script",
1351                       "Referer: http://localhost:§§PORT§§/",
1352                       "Accept-Encoding: gzip, deflate, br, zstd",
1353                       "Accept-Language: en-US,en;q=0.9"},
1354             EDGE = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1355                     "Host: localhost:§§PORT§§",
1356                     "Connection: keep-alive",
1357                     "sec-ch-ua-platform: \"Windows\"",
1358                     "User-Agent: §§USER_AGENT§§",
1359                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1360                     "sec-ch-ua-mobile: ?0",
1361                     "Accept: §§ACCEPT§§",
1362                     "Sec-Fetch-Site: same-origin",
1363                     "Sec-Fetch-Mode: no-cors",
1364                     "Sec-Fetch-Dest: script",
1365                     "Referer: http://localhost:§§PORT§§/",
1366                     "Accept-Encoding: gzip, deflate, br, zstd",
1367                     "Accept-Language: en-US,en;q=0.9"},
1368             FF = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1369                   "Host: localhost:§§PORT§§",
1370                   "User-Agent: §§USER_AGENT§§",
1371                   "Accept: §§ACCEPT§§",
1372                   "Accept-Language: en-US,en;q=0.5",
1373                   "Accept-Encoding: gzip, deflate, br, zstd",
1374                   "Connection: keep-alive",
1375                   "Referer: http://localhost:§§PORT§§/",
1376                   "Sec-Fetch-Dest: script",
1377                   "Sec-Fetch-Mode: no-cors",
1378                   "Sec-Fetch-Site: same-origin",
1379                   "Priority: u=2"},
1380             FF_ESR = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1381                       "Host: localhost:§§PORT§§",
1382                       "User-Agent: §§USER_AGENT§§",
1383                       "Accept: §§ACCEPT§§",
1384                       "Accept-Language: en-US,en;q=0.5",
1385                       "Accept-Encoding: gzip, deflate, br, zstd",
1386                       "Connection: keep-alive",
1387                       "Referer: http://localhost:§§PORT§§/",
1388                       "Sec-Fetch-Dest: script",
1389                       "Sec-Fetch-Mode: no-cors",
1390                       "Sec-Fetch-Site: same-origin",
1391                       "Priority: u=2"})
1392     @HtmlUnitNYI(CHROME = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1393                            "Host: localhost:§§PORT§§",
1394                            "Connection: keep-alive",
1395                            "sec-ch-ua: §§SEC_USER_AGENT§§",
1396                            "sec-ch-ua-mobile: ?0",
1397                            "sec-ch-ua-platform: \"Windows\"",
1398                            "Upgrade-Insecure-Requests: 1", // wrong
1399                            "User-Agent: §§USER_AGENT§§",
1400                            "Accept: §§ACCEPT§§",
1401                            "Sec-Fetch-Site: same-origin",
1402                            "Sec-Fetch-Mode: no-cors",
1403                            "Sec-Fetch-User: ?1", // wrong
1404                            "Sec-Fetch-Dest: script",
1405                            "Referer: http://localhost:§§PORT§§/",
1406                            "Accept-Encoding: gzip, deflate, br",
1407                            "Accept-Language: en-US,en;q=0.9"},
1408             EDGE = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1409                     "Host: localhost:§§PORT§§",
1410                     "Connection: keep-alive",
1411                     "sec-ch-ua: §§SEC_USER_AGENT§§",
1412                     "sec-ch-ua-mobile: ?0",
1413                     "sec-ch-ua-platform: \"Windows\"",
1414                     "Upgrade-Insecure-Requests: 1", // wrong
1415                     "User-Agent: §§USER_AGENT§§",
1416                     "Accept: §§ACCEPT§§",
1417                     "Sec-Fetch-Site: same-origin",
1418                     "Sec-Fetch-Mode: no-cors",
1419                     "Sec-Fetch-User: ?1", // wrong
1420                     "Sec-Fetch-Dest: script",
1421                     "Referer: http://localhost:§§PORT§§/",
1422                     "Accept-Encoding: gzip, deflate, br",
1423                     "Accept-Language: en-US,en;q=0.9"},
1424             FF = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1425                   "Host: localhost:§§PORT§§",
1426                   "User-Agent: §§USER_AGENT§§",
1427                   "Accept: §§ACCEPT§§",
1428                   "Accept-Language: en-US,en;q=0.5",
1429                   "Accept-Encoding: gzip, deflate, br",
1430                   "Connection: keep-alive",
1431                   "Referer: http://localhost:§§PORT§§/",
1432                   "Upgrade-Insecure-Requests: 1", // wrong
1433                   "Sec-Fetch-Dest: script",
1434                   "Sec-Fetch-Mode: no-cors",
1435                   "Sec-Fetch-Site: same-origin",
1436                   "Sec-Fetch-User: ?1", /* wrong */
1437                   "Priority: u=0, i"},
1438             FF_ESR = {"GET /script.js?x=%CE%D2%CA%C7%CE%D2%B5%C4%20?%20Abc HTTP/1.1",
1439                       "Host: localhost:§§PORT§§",
1440                       "User-Agent: §§USER_AGENT§§",
1441                       "Accept: §§ACCEPT§§",
1442                       "Accept-Language: en-US,en;q=0.5",
1443                       "Accept-Encoding: gzip, deflate, br",
1444                       "Connection: keep-alive",
1445                       "Referer: http://localhost:§§PORT§§/",
1446                       "Upgrade-Insecure-Requests: 1", // wrong
1447                       "Sec-Fetch-Dest: script",
1448                       "Sec-Fetch-Mode: no-cors",
1449                       "Sec-Fetch-Site: same-origin",
1450                       "Sec-Fetch-User: ?1", /* wrong */
1451                       "Priority: u=0, i"})
1452     // this fails on our CI but I have no idea why
1453     // seems like the request for downloading the script never reaches the
1454     // PrimitiveWebServer
1455     @DisabledOnOs(OS.LINUX)
1456     public void loadJavascriptCharset() throws Exception {
1457         String html = DOCTYPE_HTML
1458                 + "<html><head>"
1459                 + "<meta http-equiv='Content-Type' content='text/html; charset=GB2312'>"
1460                 + "<script src=\"script.js?x=\u6211\u662F\u6211\u7684 \u4eb8 Abc\"></script>"
1461                 + "</head><body></body></html>";
1462         html = "HTTP/1.1 200 OK\r\n"
1463                 + "Content-Length: " + (html.length()) + "\r\n"
1464                 + "Content-Type: text/html\r\n"
1465                 + "\r\n"
1466                 + html;
1467         final String hi = "HTTP/1.1 200 OK\r\n"
1468                 + "Content-Length: 0\r\n"
1469                 + "Content-Type: text/javascript\r\n"
1470                 + "\r\n"
1471                 + "";
1472 
1473         shutDownAll();
1474         try (PrimitiveWebServer primitiveWebServer = new PrimitiveWebServer(Charset.forName("GB2312"), html, hi)) {
1475             final WebDriver driver = getWebDriver();
1476 
1477             driver.get("http://localhost:" + primitiveWebServer.getPort());
1478 
1479             final String[] expectedHeaders = getExpectedAlerts();
1480             for (int i = 0; i < expectedHeaders.length; i++) {
1481                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§PORT§§", "" + primitiveWebServer.getPort());
1482                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§USER_AGENT§§",
1483                         getBrowserVersion().getUserAgent());
1484                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§SEC_USER_AGENT§§",
1485                         getBrowserVersion().getSecClientHintUserAgentHeader());
1486                 expectedHeaders[i] = expectedHeaders[i].replaceAll("§§ACCEPT§§",
1487                         getBrowserVersion().getScriptAcceptHeader());
1488             }
1489 
1490             // let's try some wait on our CI server
1491             final long endTime = System.currentTimeMillis() + Duration.ofSeconds(4).toMillis();
1492             while (primitiveWebServer.getRequests().size() < 1
1493                         && System.currentTimeMillis() < endTime) {
1494                 Thread.sleep(100);
1495             }
1496 
1497             if (primitiveWebServer.getRequests().size() < 2) {
1498                 Assertions.fail("Still no request / request count:" + primitiveWebServer.getRequests().size());
1499             }
1500 
1501             final String request = primitiveWebServer.getRequests().get(1);
1502             final String[] headers = request.split("\\r\\n");
1503             assertEquals(Arrays.asList(expectedHeaders).toString(), Arrays.asList(headers).toString());
1504         }
1505     }
1506 }