/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
NodeHTTPSServer,
NodeHTTP2Server,
NodeHTTPProxyServer,
NodeHTTPSProxyServer,
NodeHTTP2ProxyServer,
} = ChromeUtils.importESModule(
"resource://testing-common/NodeServer.sys.mjs");
// The certificates we use are for localhost.
Services.prefs.setBoolPref(
"network.proxy.allow_hijacking_localhost",
true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(
"network.proxy.allow_hijacking_localhost");
});
add_setup(async
function () {
const certdb = Cc[
"@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb,
"http2-ca.pem",
"CTu,u,u");
addCertFromFile(certdb,
"proxy-ca.pem",
"CTu,u,u");
});
function makeRequest(uri) {
const { promise, resolve, reject } = Promise.withResolvers();
const channel = NetUtil.newChannel({
uri,
loadUsingSystemPrincipal:
true,
});
channel.asyncOpen(
new ChannelListener((request, data) => {
try {
request.QueryInterface(Ci.nsIHttpChannel);
request.QueryInterface(Ci.nsIProxiedChannel);
resolve({ channel, data });
}
catch (e) {
reject(e);
}
})
);
return promise;
}
async
function testResponseHeaders(port) {
const { channel } = await makeRequest(`https:
//localhost:${port}/`);
Assert.equal(channel.httpProxyConnectResponseCode,
200);
Assert.equal(
channel.getHttpProxyResponseHeader(
"Proxy-agent"),
"Node.js-Proxy"
);
try {
channel.getHttpProxyResponseHeader(
"Not-existing");
Assert.ok(
false,
"We expected an exception when trying to get a non-existing header."
);
}
catch (e) {
if (e.result) {
Assert.equal(
e.result,
0x80040111,
"We got NS_ERROR_NOT_AVAILABLE from a non-existing header."
);
}
else {
throw e;
}
}
}
add_task(async
function test_response_headers() {
for (
const [serverProtocol, serverClass] of [
[
"https", NodeHTTPSServer],
[
"http2", NodeHTTP2Server],
]) {
const server =
new serverClass();
await server.start();
try {
for (
const [proxyProtocol, proxyClass] of [
[
"plain HTTP/1.1", NodeHTTPProxyServer],
[
"https HTTP/1.1", NodeHTTPSProxyServer],
[
"HTTP/2", NodeHTTP2ProxyServer],
]) {
info(
`Starting the test with a ${proxyProtocol} proxy and a ${serverProtocol} server`
);
let proxy;
try {
proxy =
new proxyClass();
await proxy.start();
await testResponseHeaders(server.port());
// Test twice to exercise keep-alive.
await testResponseHeaders(server.port());
}
finally {
await proxy?.stop();
}
}
}
finally {
await server.stop();
}
}
});