diff --git a/src/parse.ts b/src/parse.ts index b2a2e7e0..b08dfdd9 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -131,7 +131,9 @@ export function parsePath(input = ""): ParsedPath { * @returns An object with two properties: username and password. */ export function parseAuth(input = ""): ParsedAuth { - const [username, password] = input.split(":"); + const separator = input.indexOf(":"); + const username = separator === -1 ? input : input.slice(0, separator); + const password = separator === -1 ? "" : input.slice(separator + 1); return { username: decode(username), password: decode(password), diff --git a/test/parse.test.ts b/test/parse.test.ts index ba72667a..d1ec3559 100644 --- a/test/parse.test.ts +++ b/test/parse.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import { parseURL, parseHost, parseFilename } from "../src"; +import { parseURL, parseHost, parseFilename, parseAuth } from "../src"; describe("parseURL", () => { const tests = [ @@ -294,3 +294,18 @@ describe("parseFilename", () => { }); } }); + +describe("parseAuth", () => { + test.each([ + ["user:pass:word", { username: "user", password: "pass:word" }], + ["user::pass:", { username: "user", password: ":pass:" }], + ["user:pass%3Aword:tail", { username: "user", password: "pass:word:tail" }], + ["user:pass", { username: "user", password: "pass" }], + ["user", { username: "user", password: "" }], + ])( + "preserves the password after the first colon in %s", + (input, expected) => { + expect(parseAuth(input)).toEqual(expected); + }, + ); +});