150 lines
5.1 KiB
JavaScript
150 lines
5.1 KiB
JavaScript
"use strict";
|
|
|
|
const { HttpServer } = ChromeUtils.importESModule(
|
|
"resource://testing-common/httpd.sys.mjs"
|
|
);
|
|
|
|
function makeChannel(url) {
|
|
return NetUtil.newChannel({
|
|
uri: url,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
}
|
|
|
|
ChromeUtils.defineLazyGetter(this, "URL", function () {
|
|
return "http://localhost:" + httpServer.identity.primaryPort;
|
|
});
|
|
|
|
let httpServer = null;
|
|
|
|
function pathHandler(metadata, response) {
|
|
var body;
|
|
if (metadata.hasHeader("Idempotency-Key")) {
|
|
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
|
// echo back the header for further validation
|
|
let IDK = metadata.getHeader("Idempotency-Key");
|
|
response.setHeader("Idempotency-Key", IDK, false);
|
|
body = "success";
|
|
} else {
|
|
response.setStatusLine(
|
|
metadata.httpVersion,
|
|
500,
|
|
"missing Idempotency-Key"
|
|
);
|
|
body = "failed";
|
|
}
|
|
response.bodyOutputStream.write(body, body.length);
|
|
}
|
|
|
|
// Helper-method to validate that the "Idempotency-Key" value that we
|
|
// generate matches the expected format and is the same in the response.
|
|
// Meant to be called inside of a test that's been added via add_task.
|
|
function validateAutomaticallyAddedHeaderVal(chan) {
|
|
let valueFromRequest = chan.getRequestHeader("Idempotency-Key");
|
|
let valueFromResponse = chan.getResponseHeader("Idempotency-Key");
|
|
|
|
// Validate that the header's got a nonempty value, and that the
|
|
// response matches the request:
|
|
Assert.notEqual(valueFromRequest, "");
|
|
Assert.notEqual(valueFromResponse, "");
|
|
Assert.equal(valueFromRequest, valueFromResponse);
|
|
|
|
// Further validation on the value (just focusing on valueFromRequest,
|
|
// since at this point we know that valueFromResponse is equal to it):
|
|
// * We expect the value to be formatted as a nonempy double-quoted string,
|
|
// (i.e. length must be at least 3), as part of the "sf-string" syntax:
|
|
Assert.greaterOrEqual(valueFromRequest.length, 3);
|
|
Assert.ok(valueFromRequest.startsWith('"'));
|
|
Assert.ok(valueFromRequest.endsWith('"'));
|
|
|
|
// * Inside the double-quotes, we expect the value to be formatted as an
|
|
// unsigned integer. The spec doesn't require this, but that's the
|
|
// representation we use for now, so let's be sure we don't inadvertently
|
|
// stray from that format (except as a deliberate choice, which would
|
|
// involve an update to this test's expectations).
|
|
let quotedPortion = valueFromRequest.slice(1, -1);
|
|
let parsedInteger = Number.parseInt(quotedPortion);
|
|
Assert.ok(!Number.isNaN(parsedInteger));
|
|
Assert.greaterOrEqual(parsedInteger, 0);
|
|
}
|
|
|
|
add_setup(async () => {
|
|
httpServer = new HttpServer();
|
|
httpServer.registerPathHandler("/test_bug1830022", pathHandler);
|
|
httpServer.start(-1);
|
|
registerCleanupFunction(async () => await httpServer.stop());
|
|
});
|
|
|
|
// tests if we add the header for the POST request
|
|
add_task(async function idempotency_key_addition_for_post() {
|
|
let chan = makeChannel(URL + "/test_bug1830022");
|
|
chan.requestMethod = "POST";
|
|
await new Promise(resolve => {
|
|
chan.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
validateAutomaticallyAddedHeaderVal(chan);
|
|
});
|
|
|
|
// tests if we add the header for the PATCH request
|
|
add_task(async function idempotency_key_addition_for_patch() {
|
|
let chan = makeChannel(URL + "/test_bug1830022");
|
|
chan.requestMethod = "PATCH";
|
|
await new Promise(resolve => {
|
|
chan.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
validateAutomaticallyAddedHeaderVal(chan);
|
|
});
|
|
|
|
// tests Idempotency key's uniqueness
|
|
add_task(async function idempotency_key_uniqueness() {
|
|
let chan = makeChannel(URL + "/test_bug1830022");
|
|
chan.requestMethod = "POST";
|
|
await new Promise(resolve => {
|
|
chan.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
|
|
let chan2 = makeChannel(URL + "/test_bug1830022");
|
|
chan2.requestMethod = "POST";
|
|
await new Promise(resolve => {
|
|
chan2.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
|
|
Assert.notEqual(
|
|
chan.getRequestHeader("Idempotency-Key"),
|
|
chan2.getRequestHeader("Idempotency-Key")
|
|
);
|
|
|
|
// tests if the Idempotency key is same for reposts
|
|
let chan3 = makeChannel(URL + "/test_bug1830022");
|
|
chan3.requestMethod = "POST";
|
|
await new Promise(resolve => {
|
|
chan3.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
|
|
let cachekey = chan3.QueryInterface(Ci.nsICacheInfoChannel).cacheKey;
|
|
|
|
let chan4 = makeChannel(URL + "/test_bug1830022");
|
|
chan4.requestMethod = "POST";
|
|
chan4.QueryInterface(Ci.nsICacheInfoChannel).cacheKey = cachekey;
|
|
await new Promise(resolve => {
|
|
chan4.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
|
|
Assert.equal(
|
|
chan3.getRequestHeader("Idempotency-Key"),
|
|
chan4.getRequestHeader("Idempotency-Key")
|
|
);
|
|
});
|
|
|
|
// tests if we do not overwrite the header that is set before opening the channel
|
|
add_task(async function idempotency_key_addition_for_post() {
|
|
// construct the channel
|
|
let chan = makeChannel(URL + "/test_bug1830022");
|
|
chan.setRequestHeader("Idempotency-Key", "U-V-W-X-Y-Z", false);
|
|
chan.requestMethod = "POST";
|
|
await new Promise(resolve => {
|
|
chan.asyncOpen(new ChannelListener(resolve));
|
|
});
|
|
Assert.equal(chan.getRequestHeader("Idempotency-Key"), "U-V-W-X-Y-Z");
|
|
Assert.equal(chan.getResponseHeader("Idempotency-Key"), "U-V-W-X-Y-Z");
|
|
});
|