Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- Manifest: netwerk/test/unit/xpcshell.toml
/* 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
"use strict";
/* import-globals-from head_cache.js */
/* import-globals-from head_cookies.js */
/* import-globals-from head_channels.js */
/* import-globals-from head_servers.js */
function makeChan(uri, loadingUrl) {
let principal = Services.scriptSecurityManager.createContentPrincipal(
Services.io.newURI(loadingUrl),
{}
);
return NetUtil.newChannel({
uri,
loadingPrincipal: principal,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
});
}
class AuthPrompt {
constructor() {
this.QueryInterface = ChromeUtils.generateQI(["nsIAuthPrompt2"]);
}
asyncPromptAuth(channel, callback, context, encryptionLevel, authInfo) {
executeSoon(function () {
authInfo.username = "guest";
authInfo.password = "guest";
callback.onAuthAvailable(context, authInfo);
});
}
}
class AuthRequestor {
constructor(prompt) {
this.prompt = prompt;
this.QueryInterface = ChromeUtils.generateQI(["nsIInterfaceRequestor"]);
}
getInterface(iid) {
if (iid.equals(Ci.nsIAuthPrompt2)) {
return this.prompt();
}
throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
}
}
/**
* Verify HTTP/2 auth retry behavior: the server issues two 401 challenges
* and only returns 200 OK on the third request.
*
* This test ensures the channel performs two auth retries and succeeds on the
* third attempt.
*
*/
add_task(async function test_http2_auth_retry_twice() {
Services.prefs.setIntPref("network.auth.subresource-http-auth-allow", 2);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
let server = new NodeHTTP2Server();
await server.start();
registerCleanupFunction(async () => {
await server.stop();
});
await server.registerPathHandler("/test", (req, res) => {
const hasAuth =
typeof req.headers.authorization === "string" &&
!!req.headers.authorization.length;
global.count ??= 0;
global.count++;
if (!hasAuth || global.count < 3) {
res.stream.respond({
":status": 401,
"content-type": "text/plain; charset=utf-8",
"www-authenticate": 'Basic realm="secret"',
});
res.end("Unauthorized\n");
return;
}
res.stream.respond({
":status": 200,
"content-type": "text/plain; charset=utf-8",
});
res.end("OK\n");
});
let chan = makeChan(
);
chan.notificationCallbacks = new AuthRequestor(() => new AuthPrompt());
let req = await new Promise(resolve => {
chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
});
equal(req.status, Cr.NS_OK);
equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "h2");
});