summaryrefslogtreecommitdiffstats
path: root/remote/shared/ChallengeHeaderParser.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'remote/shared/ChallengeHeaderParser.sys.mjs')
-rw-r--r--remote/shared/ChallengeHeaderParser.sys.mjs74
1 files changed, 74 insertions, 0 deletions
diff --git a/remote/shared/ChallengeHeaderParser.sys.mjs b/remote/shared/ChallengeHeaderParser.sys.mjs
new file mode 100644
index 0000000000..7cb73a4146
--- /dev/null
+++ b/remote/shared/ChallengeHeaderParser.sys.mjs
@@ -0,0 +1,74 @@
+/* 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/. */
+
+/**
+ * Parse the parameter in a name/value pair and remove quotes.
+ *
+ * @param {string} paramValue
+ * A string representing a challenge parameter.
+ *
+ * @returns {object}
+ * An object with name and value string properties.
+ */
+function parseChallengeParameter(paramValue) {
+ const [name, value] = paramValue.split("=");
+ return { name, value: value?.replace(/["']/g, "") };
+}
+
+/**
+ * Simple parser for authenticate (WWW-Authenticate or Proxy-Authenticate)
+ * headers.
+ *
+ * Bug 1857847: Replace with Necko's ChallengeParser once exposed to JS.
+ *
+ * @param {string} headerValue
+ * The value of an authenticate header.
+ *
+ * @returns {Array<object>}
+ * Array of challenge objects containing two properties:
+ * - {string} scheme: The scheme for the challenge
+ * - {Array<object>} params: Array of { name, value } objects representing
+ * all the parameters of the challenge.
+ */
+export function parseChallengeHeader(headerValue) {
+ const challenges = [];
+ const parts = headerValue.split(",").map(part => part.trim());
+
+ let scheme = null;
+ let params = [];
+
+ const schemeRegex = /^(\w+)(?:\s+(.*))?$/;
+ for (const part of parts) {
+ const matches = part.match(schemeRegex);
+ if (matches !== null) {
+ // This is a new scheme.
+ if (scheme !== null) {
+ // If we have a challenge recorded, add it to the array.
+ challenges.push({ scheme, params });
+ }
+
+ // Reset the state for a new scheme.
+ scheme = matches[1];
+ params = [];
+ if (matches[2]) {
+ params.push(parseChallengeParameter(matches[2]));
+ }
+ } else {
+ if (scheme === null) {
+ // A scheme should always be found before parameters, this header
+ // probably needs a more careful parsing solution.
+ return [];
+ }
+
+ params.push(parseChallengeParameter(part));
+ }
+ }
+
+ if (scheme !== null) {
+ // If we have a challenge recorded, add it to the array.
+ challenges.push({ scheme, params });
+ }
+
+ return challenges;
+}