1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * This test checks following expectations when using HTTP/2 proxy:
10 * - when we request https access, we don't create different sessions for
11 * different origins, only new tunnels inside a single session
12 * - when the isolation key (`proxy_isolation`) is changed, new single session
13 * is created for new requests to same origins as before
14 * - error code returned from the tunnel (a proxy error - not end-server
15 * error!) doesn't kill the existing session
16 * - check we are seeing expected nsresult error codes on channels
17 * (nsIChannel.status) corresponding to different proxy status code
18 * responses (502, 504, 407, ...)
19 * - check we don't try to ask for credentials or otherwise authenticate to
20 * the proxy when 407 is returned and there is no Proxy-Authenticate
21 * response header sent
22 * - a stream reset for a connect stream to the proxy does not cause session to
23 * be closed and the request through the proxy will failed.
24 * - a "soft" stream error on a connection to the origin server will close the
25 * stream, but it will not close niether the HTTP/2 session to the proxy nor
26 * to the origin server.
27 * - a "hard" stream error on a connection to the origin server will close the
28 * HTTP/2 session to the origin server, but it will not close the HTTP/2
29 * session to the proxy.
33 /* global serverPort */
37 const pps
= Cc
["@mozilla.org/network/protocol-proxy-service;1"].getService();
44 const proxy_auth
= "authorization-token";
48 constructor(type
, host
, port
, flags
) {
53 this.QueryInterface
= ChromeUtils
.generateQI(["nsIProtocolProxyFilter"]);
55 applyFilter(uri
, pi
, cb
) {
56 cb
.onProxyFilterResult(
71 class UnxpectedAuthPrompt2
{
74 this.QueryInterface
= ChromeUtils
.generateQI(["nsIAuthPrompt2"]);
77 this.signal
.triggered
= true;
78 throw Components
.Exception("", Cr
.ERROR_UNEXPECTED
);
82 class SimpleAuthPrompt2
{
85 this.QueryInterface
= ChromeUtils
.generateQI(["nsIAuthPrompt2"]);
87 asyncPromptAuth(channel
, callback
, context
, encryptionLevel
, authInfo
) {
88 this.signal
.triggered
= true;
89 executeSoon(function () {
90 authInfo
.username
= "user";
91 authInfo
.password
= "pass";
92 callback
.onAuthAvailable(context
, authInfo
);
100 this.QueryInterface
= ChromeUtils
.generateQI(["nsIInterfaceRequestor"]);
103 if (iid
.equals(Ci
.nsIAuthPrompt2
)) {
104 return this.prompt();
106 throw Components
.Exception("", Cr
.NS_ERROR_NO_INTERFACE
);
110 function createPrincipal(url
) {
111 var ssm
= Services
.scriptSecurityManager
;
113 return ssm
.createContentPrincipal(Services
.io
.newURI(url
), {});
119 function make_channel(url
) {
120 return NetUtil
.newChannel({
122 loadingPrincipal
: createPrincipal(url
),
123 securityFlags
: Ci
.nsILoadInfo
.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
,
124 // Using TYPE_DOCUMENT for the authentication dialog test, it'd be blocked for other types
125 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
129 function get_response(channel
, flags
= CL_ALLOW_UNKNOWN_CL
, delay
= 0) {
130 return new Promise(resolve
=> {
131 var listener
= new ChannelListener(
133 request
.QueryInterface(Ci
.nsIHttpChannel
);
134 const status
= request
.status
;
135 const http_code
= status
? undefined : request
.responseStatus
;
136 request
.QueryInterface(Ci
.nsIProxiedChannel
);
137 const proxy_connect_response_code
=
138 request
.httpProxyConnectResponseCode
;
139 resolve({ status
, http_code
, data
, proxy_connect_response_code
});
145 do_timeout(delay
, function () {
146 channel
.asyncOpen(listener
);
149 channel
.asyncOpen(listener
);
154 let initial_session_count
= 0;
156 class http2ProxyCode
{
157 static listen(server
, envport
) {
159 return Promise
.resolve(0);
162 let portSelection
= 0;
163 if (envport
!== undefined) {
165 portSelection
= parseInt(envport
, 10);
170 return new Promise(resolve
=> {
171 server
.listen(portSelection
, "0.0.0.0", 2000, () => {
172 resolve(server
.address().port
);
177 static startNewProxy() {
178 const fs
= require("fs");
180 key
: fs
.readFileSync(__dirname
+ "/http2-cert.key"),
181 cert
: fs
.readFileSync(__dirname
+ "/http2-cert.pem"),
183 const http2
= require("http2");
184 global
.proxy
= http2
.createSecureServer(options
);
186 return http2ProxyCode
.listen(proxy
).then(port
=> {
187 return { port
, success
: true };
191 static closeProxy() {
192 proxy
.closeSockets();
193 return new Promise(resolve
=> {
194 proxy
.close(resolve
);
198 static proxySessionCount() {
202 return proxy
.proxy_session_count
;
205 static proxySessionToOriginServersCount() {
209 return proxy
.sessionToOriginServersCount
;
212 static setupProxy() {
214 throw new Error("proxy is null");
216 proxy
.proxy_session_count
= 0;
217 proxy
.sessionToOriginServersCount
= 0;
218 proxy
.on("session", () => {
219 ++proxy
.proxy_session_count
;
222 // We need to track active connections so we can forcefully close keep-alive
223 // connections when shutting down the proxy.
224 proxy
.socketIndex
= 0;
225 proxy
.socketMap
= {};
226 proxy
.on("connection", function (socket
) {
227 let index
= proxy
.socketIndex
++;
228 proxy
.socketMap
[index
] = socket
;
229 socket
.on("close", function () {
230 delete proxy
.socketMap
[index
];
233 proxy
.closeSockets = function () {
234 for (let i
in proxy
.socketMap
) {
235 proxy
.socketMap
[i
].destroy();
239 proxy
.on("stream", (stream
, headers
) => {
240 if (headers
[":method"] !== "CONNECT") {
241 // Only accept CONNECT requests
242 stream
.respond({ ":status": 405 });
247 const target
= headers
[":authority"];
249 const authorization_token
= headers
["proxy-authorization"];
250 if (target
== "407.example.com:443") {
251 stream
.respond({ ":status": 407 });
252 // Deliberately send no Proxy-Authenticate header
256 if (target
== "407.basic.example.com:443") {
257 // we want to return a different response than 407 to not re-request
258 // credentials (and thus loop) but also not 200 to not let the channel
259 // attempt to waste time connecting a non-existing https server - hence
260 // 418 I'm a teapot :)
261 if ("Basic dXNlcjpwYXNz" == authorization_token
) {
262 stream
.respond({ ":status": 418 });
268 "proxy-authenticate": "Basic realm='foo'",
273 if (target
== "404.example.com:443") {
274 // 404 Not Found, a response code that a proxy should return when the host can't be found
275 stream
.respond({ ":status": 404 });
279 if (target
== "429.example.com:443") {
280 // 429 Too Many Requests, a response code that a proxy should return when receiving too many requests
281 stream
.respond({ ":status": 429 });
285 if (target
== "502.example.com:443") {
286 // 502 Bad Gateway, a response code mostly resembling immediate connection error
287 stream
.respond({ ":status": 502 });
291 if (target
== "504.example.com:443") {
292 // 504 Gateway Timeout, did not receive a timely response from an upstream server
293 stream
.respond({ ":status": 504 });
297 if (target
== "reset.example.com:443") {
298 // always reset the stream.
303 ++proxy
.sessionToOriginServersCount
;
304 const net
= require("net");
305 const socket
= net
.connect(serverPort
, "127.0.0.1", () => {
307 stream
.respond({ ":status": 200 });
310 } catch (exception
) {
311 console
.log(exception
);
315 socket
.on("error", error
=> {
317 `Unexpected error when conneting the HTTP/2 server from the HTTP/2 proxy during CONNECT handling: '${error}'`
324 async
function proxy_session_counter() {
325 let data
= await NodeServer
.execute(
327 `http2ProxyCode.proxySessionCount()`
329 return parseInt(data
) - initial_session_count
;
331 async
function proxy_session_to_origin_server_counter() {
332 let data
= await NodeServer
.execute(
334 `http2ProxyCode.proxySessionToOriginServersCount()`
336 return parseInt(data
) - initial_session_count
;
339 add_task(async
function setup() {
340 // Set to allow the cert presented by our H2 server
343 // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
344 // so add that cert to the trust list as a signing cert.
345 let certdb
= Cc
["@mozilla.org/security/x509certdb;1"].getService(
348 addCertFromFile(certdb
, "http2-ca.pem", "CTu,u,u");
350 let server_port
= Services
.env
.get("MOZHTTP2_PORT");
351 Assert
.notEqual(server_port
, null);
352 processId
= await NodeServer
.fork();
353 await NodeServer
.execute(processId
, `serverPort = ${server_port}`);
354 await NodeServer
.execute(processId
, http2ProxyCode
);
355 let newProxy
= await NodeServer
.execute(
357 `http2ProxyCode.startNewProxy()`
359 proxy_port
= newProxy
.port
;
360 Assert
.notEqual(proxy_port
, null);
362 Services
.prefs
.setStringPref(
363 "services.settings.server",
364 `data:,#remote-settings-dummy/v1`
367 Services
.prefs
.setBoolPref("network.http.http2.enabled", true);
369 // Even with network state isolation active, we don't end up using the
370 // partitioned principal.
371 Services
.prefs
.setBoolPref("privacy.partition.network_state", true);
373 // make all native resolve calls "secretly" resolve localhost instead
374 Services
.prefs
.setBoolPref("network.dns.native-is-localhost", true);
376 filter
= new ProxyFilter("https", "localhost", proxy_port
, 0);
377 pps
.registerFilter(filter
, 10);
379 initial_session_count
= await
proxy_session_counter();
380 info(`Initial proxy session count = ${initial_session_count}`);
383 registerCleanupFunction(async () => {
384 Services
.prefs
.clearUserPref("services.settings.server");
385 Services
.prefs
.clearUserPref("network.http.http2.enabled");
386 Services
.prefs
.clearUserPref("network.dns.native-is-localhost");
388 pps
.unregisterFilter(filter
);
390 await NodeServer
.execute(processId
, `http2ProxyCode.closeProxy()`);
391 await NodeServer
.kill(processId
);
395 * Test series beginning.
398 // Check we reach the h2 end server and keep only one session with the proxy for two different origin.
399 // Here we use the first isolation token.
400 add_task(async
function proxy_success_one_session() {
401 proxy_isolation
= "TOKEN1";
403 const foo
= await
get_response(
404 make_channel(`https://foo.example.com/random-request-1`)
406 const alt1
= await
get_response(
407 make_channel(`https://alt1.example.com/random-request-2`)
410 Assert
.equal(foo
.status
, Cr
.NS_OK
);
411 Assert
.equal(foo
.proxy_connect_response_code
, 200);
412 Assert
.equal(foo
.http_code
, 200);
413 Assert
.ok(foo
.data
.match("random-request-1"));
414 Assert
.ok(foo
.data
.match("You Win!"));
415 Assert
.equal(alt1
.status
, Cr
.NS_OK
);
416 Assert
.equal(alt1
.proxy_connect_response_code
, 200);
417 Assert
.equal(alt1
.http_code
, 200);
418 Assert
.ok(alt1
.data
.match("random-request-2"));
419 Assert
.ok(alt1
.data
.match("You Win!"));
421 await
proxy_session_counter(),
423 "Created just one session with the proxy"
427 // The proxy responses with 407 instead of 200 Connected, make sure we get a proper error
428 // code from the channel and not try to ask for any credentials.
429 add_task(async
function proxy_auth_failure() {
430 const chan
= make_channel(`https://407.example.com/`);
431 const auth_prompt
= { triggered
: false };
432 chan
.notificationCallbacks
= new AuthRequestor(
433 () => new UnxpectedAuthPrompt2(auth_prompt
)
435 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
440 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_AUTHENTICATION_FAILED
);
441 Assert
.equal(proxy_connect_response_code
, 407);
442 Assert
.equal(http_code
, undefined);
443 Assert
.equal(auth_prompt
.triggered
, false, "Auth prompt didn't trigger");
445 await
proxy_session_counter(),
447 "No new session created by 407"
451 // The proxy responses with 407 with Proxy-Authenticate header presence. Make
452 // sure that we prompt the auth prompt to ask for credentials.
453 add_task(async
function proxy_auth_basic() {
454 const chan
= make_channel(`https://407.basic.example.com/`);
455 const auth_prompt
= { triggered
: false };
456 chan
.notificationCallbacks
= new AuthRequestor(
457 () => new SimpleAuthPrompt2(auth_prompt
)
459 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
464 // 418 indicates we pass the basic authentication.
465 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_CONNECTION_REFUSED
);
466 Assert
.equal(proxy_connect_response_code
, 418);
467 Assert
.equal(http_code
, undefined);
468 Assert
.equal(auth_prompt
.triggered
, true, "Auth prompt should trigger");
470 await
proxy_session_counter(),
472 "No new session created by 407"
476 // 502 Bad gateway code returned by the proxy, still one session only, proper different code
478 add_task(async
function proxy_bad_gateway_failure() {
479 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
480 make_channel(`https://502.example.com/`),
484 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_BAD_GATEWAY
);
485 Assert
.equal(proxy_connect_response_code
, 502);
486 Assert
.equal(http_code
, undefined);
488 await
proxy_session_counter(),
490 "No new session created by 502 after 407"
494 // Second 502 Bad gateway code returned by the proxy, still one session only with the proxy.
495 add_task(async
function proxy_bad_gateway_failure_two() {
496 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
497 make_channel(`https://502.example.com/`),
501 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_BAD_GATEWAY
);
502 Assert
.equal(proxy_connect_response_code
, 502);
503 Assert
.equal(http_code
, undefined);
505 await
proxy_session_counter(),
507 "No new session created by second 502"
511 // 504 Gateway timeout code returned by the proxy, still one session only, proper different code
513 add_task(async
function proxy_gateway_timeout_failure() {
514 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
515 make_channel(`https://504.example.com/`),
519 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_GATEWAY_TIMEOUT
);
520 Assert
.equal(proxy_connect_response_code
, 504);
521 Assert
.equal(http_code
, undefined);
523 await
proxy_session_counter(),
525 "No new session created by 504 after 502"
529 // 404 Not Found means the proxy could not resolve the host. As for other error responses
530 // we still expect this not to close the existing session.
531 add_task(async
function proxy_host_not_found_failure() {
532 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
533 make_channel(`https://404.example.com/`),
537 Assert
.equal(status
, Cr
.NS_ERROR_UNKNOWN_HOST
);
538 Assert
.equal(proxy_connect_response_code
, 404);
539 Assert
.equal(http_code
, undefined);
541 await
proxy_session_counter(),
543 "No new session created by 404 after 504"
547 add_task(async
function proxy_too_many_requests_failure() {
548 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
549 make_channel(`https://429.example.com/`),
553 Assert
.equal(status
, Cr
.NS_ERROR_PROXY_TOO_MANY_REQUESTS
);
554 Assert
.equal(proxy_connect_response_code
, 429);
555 Assert
.equal(http_code
, undefined);
557 await
proxy_session_counter(),
559 "No new session created by 429 after 504"
563 add_task(async
function proxy_stream_reset_failure() {
564 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
565 make_channel(`https://reset.example.com/`),
569 Assert
.equal(status
, Cr
.NS_ERROR_NET_INTERRUPT
);
570 Assert
.equal(proxy_connect_response_code
, 0);
571 Assert
.equal(http_code
, undefined);
573 await
proxy_session_counter(),
575 "No new session created by 429 after 504"
579 // The soft errors are not closing the session.
580 add_task(async
function origin_server_stream_soft_failure() {
581 var current_num_sessions_to_origin_server
=
582 await
proxy_session_to_origin_server_counter();
584 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
585 make_channel(`https://foo.example.com/illegalhpacksoft`),
589 Assert
.equal(status
, Cr
.NS_ERROR_ILLEGAL_VALUE
);
590 Assert
.equal(proxy_connect_response_code
, 200);
591 Assert
.equal(http_code
, undefined);
593 await
proxy_session_counter(),
595 "No session to the proxy closed by soft stream errors"
598 await
proxy_session_to_origin_server_counter(),
599 current_num_sessions_to_origin_server
,
600 "No session to the origin server closed by soft stream errors"
604 // The soft errors are not closing the session.
606 async
function origin_server_stream_soft_failure_multiple_streams_not_affected() {
607 var current_num_sessions_to_origin_server
=
608 await
proxy_session_to_origin_server_counter();
610 let should_succeed
= get_response(
611 make_channel(`https://foo.example.com/750ms`)
614 const failed
= await
get_response(
615 make_channel(`https://foo.example.com/illegalhpacksoft`),
620 const succeeded
= await should_succeed
;
622 Assert
.equal(failed
.status
, Cr
.NS_ERROR_ILLEGAL_VALUE
);
623 Assert
.equal(failed
.proxy_connect_response_code
, 200);
624 Assert
.equal(failed
.http_code
, undefined);
625 Assert
.equal(succeeded
.status
, Cr
.NS_OK
);
626 Assert
.equal(succeeded
.proxy_connect_response_code
, 200);
627 Assert
.equal(succeeded
.http_code
, 200);
629 await
proxy_session_counter(),
631 "No session to the proxy closed by soft stream errors"
634 await
proxy_session_to_origin_server_counter(),
635 current_num_sessions_to_origin_server
,
636 "No session to the origin server closed by soft stream errors"
641 // Make sure that the above error codes don't kill the session to the proxy.
642 add_task(async
function proxy_success_still_one_session() {
643 const foo
= await
get_response(
644 make_channel(`https://foo.example.com/random-request-1`)
646 const alt1
= await
get_response(
647 make_channel(`https://alt1.example.com/random-request-2`)
650 Assert
.equal(foo
.status
, Cr
.NS_OK
);
651 Assert
.equal(foo
.http_code
, 200);
652 Assert
.equal(foo
.proxy_connect_response_code
, 200);
653 Assert
.ok(foo
.data
.match("random-request-1"));
654 Assert
.equal(alt1
.status
, Cr
.NS_OK
);
655 Assert
.equal(alt1
.proxy_connect_response_code
, 200);
656 Assert
.equal(alt1
.http_code
, 200);
657 Assert
.ok(alt1
.data
.match("random-request-2"));
659 await
proxy_session_counter(),
661 "No new session to the proxy created after stream error codes"
665 // Have a new isolation key, this means we are expected to create a new, and again one only,
666 // session with the proxy to reach the end server.
667 add_task(async
function proxy_success_isolated_session() {
668 Assert
.notEqual(proxy_isolation
, "TOKEN2");
669 proxy_isolation
= "TOKEN2";
671 const foo
= await
get_response(
672 make_channel(`https://foo.example.com/random-request-1`)
674 const alt1
= await
get_response(
675 make_channel(`https://alt1.example.com/random-request-2`)
677 const lh
= await
get_response(
678 make_channel(`https://localhost/random-request-3`)
681 Assert
.equal(foo
.status
, Cr
.NS_OK
);
682 Assert
.equal(foo
.proxy_connect_response_code
, 200);
683 Assert
.equal(foo
.http_code
, 200);
684 Assert
.ok(foo
.data
.match("random-request-1"));
685 Assert
.ok(foo
.data
.match("You Win!"));
686 Assert
.equal(alt1
.status
, Cr
.NS_OK
);
687 Assert
.equal(alt1
.proxy_connect_response_code
, 200);
688 Assert
.equal(alt1
.http_code
, 200);
689 Assert
.ok(alt1
.data
.match("random-request-2"));
690 Assert
.ok(alt1
.data
.match("You Win!"));
691 Assert
.equal(lh
.status
, Cr
.NS_OK
);
692 Assert
.equal(lh
.proxy_connect_response_code
, 200);
693 Assert
.equal(lh
.http_code
, 200);
694 Assert
.ok(lh
.data
.match("random-request-3"));
695 Assert
.ok(lh
.data
.match("You Win!"));
697 await
proxy_session_counter(),
699 "Just one new session seen after changing the isolation key"
703 // Check that error codes are still handled the same way with new isolation, just in case.
704 add_task(async
function proxy_bad_gateway_failure_isolated() {
705 const failure1
= await
get_response(
706 make_channel(`https://502.example.com/`),
709 const failure2
= await
get_response(
710 make_channel(`https://502.example.com/`),
714 Assert
.equal(failure1
.status
, Cr
.NS_ERROR_PROXY_BAD_GATEWAY
);
715 Assert
.equal(failure1
.proxy_connect_response_code
, 502);
716 Assert
.equal(failure1
.http_code
, undefined);
717 Assert
.equal(failure2
.status
, Cr
.NS_ERROR_PROXY_BAD_GATEWAY
);
718 Assert
.equal(failure2
.proxy_connect_response_code
, 502);
719 Assert
.equal(failure2
.http_code
, undefined);
721 await
proxy_session_counter(),
723 "No new session created by 502"
727 add_task(async
function proxy_success_check_number_of_session() {
728 const foo
= await
get_response(
729 make_channel(`https://foo.example.com/random-request-1`)
731 const alt1
= await
get_response(
732 make_channel(`https://alt1.example.com/random-request-2`)
734 const lh
= await
get_response(
735 make_channel(`https://localhost/random-request-3`)
738 Assert
.equal(foo
.status
, Cr
.NS_OK
);
739 Assert
.equal(foo
.proxy_connect_response_code
, 200);
740 Assert
.equal(foo
.http_code
, 200);
741 Assert
.ok(foo
.data
.match("random-request-1"));
742 Assert
.ok(foo
.data
.match("You Win!"));
743 Assert
.equal(alt1
.status
, Cr
.NS_OK
);
744 Assert
.equal(alt1
.proxy_connect_response_code
, 200);
745 Assert
.equal(alt1
.http_code
, 200);
746 Assert
.ok(alt1
.data
.match("random-request-2"));
747 Assert
.ok(alt1
.data
.match("You Win!"));
748 Assert
.equal(lh
.status
, Cr
.NS_OK
);
749 Assert
.equal(lh
.proxy_connect_response_code
, 200);
750 Assert
.equal(lh
.http_code
, 200);
751 Assert
.ok(lh
.data
.match("random-request-3"));
752 Assert
.ok(lh
.data
.match("You Win!"));
754 await
proxy_session_counter(),
756 "The number of sessions has not changed"
760 // The hard errors are closing the session.
761 add_task(async
function origin_server_stream_hard_failure() {
762 var current_num_sessions_to_origin_server
=
763 await
proxy_session_to_origin_server_counter();
764 const { status
, http_code
, proxy_connect_response_code
} = await
get_response(
765 make_channel(`https://foo.example.com/illegalhpackhard`),
769 Assert
.equal(status
, 0x804b0053);
770 Assert
.equal(proxy_connect_response_code
, 200);
771 Assert
.equal(http_code
, undefined);
773 await
proxy_session_counter(),
775 "No new session to the proxy."
778 await
proxy_session_to_origin_server_counter(),
779 current_num_sessions_to_origin_server
,
780 "No new session to the origin server yet."
783 // Check the a new session ill be opened.
784 const foo
= await
get_response(
785 make_channel(`https://foo.example.com/random-request-1`)
788 Assert
.equal(foo
.status
, Cr
.NS_OK
);
789 Assert
.equal(foo
.proxy_connect_response_code
, 200);
790 Assert
.equal(foo
.http_code
, 200);
791 Assert
.ok(foo
.data
.match("random-request-1"));
792 Assert
.ok(foo
.data
.match("You Win!"));
795 await
proxy_session_counter(),
797 "No new session to the proxy is created after a hard stream failure on the session to the origin server."
800 await
proxy_session_to_origin_server_counter(),
801 current_num_sessions_to_origin_server
+ 1,
802 "A new session to the origin server after a hard stream error"
806 // The hard errors are closing the session.
808 async
function origin_server_stream_hard_failure_multiple_streams_affected() {
809 var current_num_sessions_to_origin_server
=
810 await
proxy_session_to_origin_server_counter();
811 let should_fail
= get_response(
812 make_channel(`https://foo.example.com/750msNoData`),
815 const failed1
= await
get_response(
816 make_channel(`https://foo.example.com/illegalhpackhard`),
821 const failed2
= await should_fail
;
823 Assert
.equal(failed1
.status
, 0x804b0053);
824 Assert
.equal(failed1
.proxy_connect_response_code
, 200);
825 Assert
.equal(failed1
.http_code
, undefined);
826 Assert
.equal(failed2
.status
, 0x804b0053);
827 Assert
.equal(failed2
.proxy_connect_response_code
, 200);
828 Assert
.equal(failed2
.http_code
, undefined);
830 await
proxy_session_counter(),
832 "No new session to the proxy"
835 await
proxy_session_to_origin_server_counter(),
836 current_num_sessions_to_origin_server
,
837 "No session to the origin server yet."
839 // Check the a new session ill be opened.
840 const foo
= await
get_response(
841 make_channel(`https://foo.example.com/random-request-1`)
844 Assert
.equal(foo
.status
, Cr
.NS_OK
);
845 Assert
.equal(foo
.proxy_connect_response_code
, 200);
846 Assert
.equal(foo
.http_code
, 200);
847 Assert
.ok(foo
.data
.match("random-request-1"));
848 Assert
.ok(foo
.data
.match("You Win!"));
851 await
proxy_session_counter(),
853 "No new session to the proxy is created after a hard stream failure on the session to the origin server."
857 await
proxy_session_to_origin_server_counter(),
858 current_num_sessions_to_origin_server
+ 1,
859 "A new session to the origin server after a hard stream error"